天天看點

Spring架構中@Qualifier()注解的使用及UnsatisfiedDependencyException和NoSuchBeanDefinitionException産生的原因

Spring架構中@Qualifier()注解的使用

以Spring架構配置檔案的QueryRunner為例,配置檔案中QueryRunner的id為queryRunner

<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
    <constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
           

dao層的實作類對象需要QueryRunner對象,将QueryRunner向上抽取到成員位置,并交給spring管理

标簽解讀:

@AutoWired,按類型注入(Spring提供),如果按類型無法唯一的定位對象,那麼就需要結合@Qualifier一起使用(隻聲明屬性即可,不需要setXXX方法)

@Resource,按id注入(JDK提供),參數指定bean的id

為了更好的區分@Resource,按id注入

配置檔案中QueryRunner的id值,取為queryRunner

dao層的實作類對象中QueryRunner對象的名字取為qr;

dao層接口的實作類對象

@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Autowired
    @Qualifier("queryRunner")
    //錯誤了解 @Qualifier("qr")
    private QueryRunner qr;

    @Override
    public List<User> queryAll() throws Exception {
        String sql="select * from user";
        return qr.query(sql,new BeanListHandler<>(User.class));
    }
}
           

dao層接口

public interface UserDao {
    //查詢所有
    List<User> queryAll() throws Exception;
}
           

service層的接口

public interface UserService {
    //查詢所有
    List<User> queryAll() throws Exception;
}
           

service層的實作類對象

@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
    @Override
    public List<User> queryAll() throws Exception {
        List<User> users = userDao.queryAll();
        return users;
    }
}
           

測試代碼

@Test
   public void text01() throws Exception {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applictionContext.xml");
      UserServiceImpl userService = context.getBean("userService", UserServiceImpl.class);
      List<User> users = userService.queryAll();
      users.forEach(System.out::println);
   }
           

如果用錯誤的@Qualifier(“qr”)注解,配置檔案中運作,異常的主要資訊為:UnsatisfiedDependencyException和NoSuchBeanDefinitionException

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userDao': Unsatisfied dependency expressed through field 'qr'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.commons.dbutils.QueryRunner' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=qr)}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.commons.dbutils.QueryRunner' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=qr)}
           
如果将配置檔案中bean id="queryRunner"改為<bean id="qr">,dao層使用 @Qualifier("qr"),就可以正常編譯運作
配置檔案中<bean id="queryRunner">,dao層使用 @Qualifier("qr"),則編譯失敗
配置檔案中<bean id="queryRunner">,dao層使用 @Qualifier("queryRunner"),可以正常編譯運作
           

通過代碼測試發現,@Qualifier()注解中傳遞的是對應bean标簽的id值.

與dao層實作類對象中成員位置上 QueryRunner對象的變量名無關,

驗證了@Resource(),按id注入(JDK提供),參數指定bean的id

為了以後不混淆,建議将對象的變量名與标簽的id值起為同一名字

繼續閱讀