Spring项目出现UnsatisfiedDependencyException异常及注解使用咨询
Great question! Let's break this down step by step, covering both your annotation question and the error you're seeing.
核心问题:能不能在DAO/Service接口和实现类上同时标注@Repository/@Service?
绝对不要在接口上标注@Repository、@Service这类 stereotype 注解。原因很简单:
- 这些注解的作用是告诉Spring:“这个类是一个需要被你管理的Bean,请为它创建实例”。但接口本身无法被实例化,Spring根本没法创建接口的Bean对象。
- 在接口上加这些注解不仅完全没用,还会干扰Spring的Bean扫描逻辑,甚至间接导致你现在遇到的类型不匹配错误。
你应该只在具体的实现类上标注这些注解:比如UserDaoImpl上的@Repository、UserServiceImpl上的@Service是正确的,但UserDao接口上的@Repository、UserService接口上的@Service必须删掉。
为什么会出现BeanNotOfRequiredTypeException错误?
Let's look at your error message again:
Bean named 'userDaoImpl' is expected to be of type 'com.project.shopping.dao.impl.UserDaoImpl' but was actually of type 'com.sun.proxy.$Proxy56'
Here's the root cause:
- 你给
UserDaoImpl加了@Transactional注解,Spring会为这个类创建JDK动态代理(因为它实现了UserDao接口)。JDK动态代理的本质是生成一个实现了目标接口的代理类,而不是继承目标类的子类。 - 但你在
UserServiceImpl里注入的是UserDaoImpl(具体类类型),而Spring实际创建的代理对象是UserDao接口类型的。这就导致了类型不匹配——你试图把一个接口类型的代理对象塞进一个具体类类型的字段里,Spring自然会报错。
同样的问题也出现在你的UserController里,你注入的是UserServiceImpl具体类,而不是UserService接口。
修复步骤
1. 移除接口上的多余注解
修改UserDao.java,删掉@Repository:
// 去掉@Repository注解 public interface UserDao { public List<User> getAllUser(); }
修改UserService.java,删掉@Service:
// 去掉@Service注解 public interface UserService { public List<User> listUser(); }
2. 改为注入接口类型而非具体实现类
修改UserServiceImpl.java,把注入的类型改成UserDao接口:
@Service public class UserServiceImpl implements UserService { // 改为注入UserDao接口,而非UserDaoImpl具体类 @Autowired private UserDao userDao; public List<User> listUser() { return userDao.getAllUser(); } }
修改UserController.java,把注入的类型改成UserService接口:
@Controller @RequestMapping("/") public class UserController { // 改为注入UserService接口,而非UserServiceImpl具体类 @Autowired UserService userService; @RequestMapping(method = RequestMethod.GET,value = "/allusers" , produces = "application/json") @ResponseBody public List<User> sayHello(ModelMap model) { return userService.listUser(); } }
3. 额外检查:确保事务配置正确
虽然这不是当前错误的直接原因,但要确保你的Spring配置中已经正确配置了事务管理器,比如:
@Configuration @EnableTransactionManagement @ComponentScan(basePackages = "com.project.shopping") public class AppConfig { // 配置SessionFactory和TransactionManager的代码... }
总结一下
- 只在具体实现类上标注
@Repository、@Service、@Controller等注解,接口不需要这些注解。 - 依赖注入时始终依赖接口类型,而不是具体实现类——这不仅符合面向对象的依赖倒置原则,还能完美适配Spring的动态代理机制,避免类型不匹配的问题。
内容的提问来源于stack exchange,提问作者Bishwa Karki

