最近想把一个项目中,创建对象的方式从xml配置文件改成注解,偶然发现了一个小问题:
我们知道当对引用类型自动注入时,使用 @Autowired() 的默认方式是byType,这就导致了,如果在spring容器中存在两个及以上的同类型但是不同名的对象,spring就无法通过byType的方式完成自动注入,因为这些对象都符合类型的要求,不知道要用哪个,这时就需要使用 @Autowired() + @Qualifier() 的组合(也可以使用jdk提供的@Resouce),通过byName方式实现自动注入。
一、两个Dao和一个Service的实现类如下
@Repository("mysqlDao")
public class UserDaoImpl implements UserDao {
@Override
public void insertUser(SysUser user) {
System.out.println("user插入到mysql数据库");
}
}
@Repository("oracleDao")
public class OracleDaoImpl implements UserDao {
@Override
public void insertUser(SysUser user) {
System.out.println("Oracle数据库连接");
}
}
@Service("userService")
public class UserServiceImpl implements UserService {
//@Resource(name = "oracleDao")
@Autowired()
@Qualifier("oracleDao")
private UserDao dao = null;
public UserServiceImpl(UserDao dao) {
this.dao = dao;
}
@Override
public void addUser(SysUser user) {
dao.insertUser(user);
}
}
二、关键报错信息
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.qhdx.dao.UserDao' available: expected single matching bean but found 2: oracleDao,mysqlDao
关键错误信息:expected single matching bean but found 2
如果没有使用 @Autowired() + @Qualifier() 的byName方式,单独使用@Autowired()的话,我们都知道会出现这个错误信息,但是已经使用了两者结合的方式,其实是不应该出现错误的。
仔细检查代码后,我发现了一个问题,我的Service实现类,也就是上面的最后一个类中,写了一个有参构造函数,这就是导致问题出现的关键。
spring在创建对象的时候,会调用类的无参构造,而我写的有参构造会将无参构造覆盖掉,这也就导致了spring无法完成对象的创建,所以会导致出错。
三、解决方法
很简单,要么将自己写的有参构造注释掉,要么加上一个无参构造,再次运行就不会报错
@Service("userService")
public class UserServiceImpl implements UserService {
//@Resource(name = "oracleDao")
@Autowired()
@Qualifier("oracleDao")
private UserDao dao = null;
/*
public UserServiceImpl(UserDao dao) {
this.dao = dao;
}
*/
@Override
public void addUser(SysUser user) {
dao.insertUser(user);
}
}
四、总结
如果要使用有参构造,那么要记得将无参构造也写出来,会节省很多麻烦。
此外身为学生党,其实还有很多不懂的问题,对于这个问题我也只是找到了解决方式和浅显的原因而已,依然有很多不明白的地方。
还是这个例子,当我只创建一个对象的时候,使用 @Autowired() 的默认自动注入,即使有参构造函数存在,我也没有写无参构造函数,程序依然可以运行,对此不是很明白,欢迎各位指点!