三分钟学会@Autowired@Qualifier@Primary注解

简介: spring自动装配相关的@Autowired,@Qualifier和@Primary注解

1,@Autowired注解的使用

继续上文深入理解spring注解之@ComponentScan注解中的例子,现在我们需要在UserService中调用UserDao相关操作,那我们可以在UserService中增加如下代码:

import com.zhang.dao.UserDao;
@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    /**
     * 增加一个tostring方法 方便测试
     */
    @Override
    public String toString() {
        return "UserService [userDao=" + userDao + "]";
    }
}

测试代码如下:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainScanConfig.class);
UserService object = (UserService) applicationContext2.getBean("userService");
System.out.println("实例bean为 === "+object);

运行结果如下:

实例bean为 === UserService [userDao=com.zhang.dao.UserDao@51b279c9]

根据运行结果我们可以发现userDao已经成功注入到UserService中了

假设现在业务中有一种情况是UserDao是第三方提供的服务,我们也不能保证其是否可以成功加入到spring容器中,那我们也不能因为UserDao没能成功注入到spring容器而使我们整个UserService服务都不能使用,那这边我们就来演示一下这种情况,如下我们注释掉UserDao的@Repository注解:

import org.springframework.stereotype.Repository;
//@Repository
public class UserDao {
}

这个时候你再启动测试类会报如下错误:

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'userDao'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zhang.dao.UserDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'userDao'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zhang.dao.UserDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1268)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
    at com.zhang.ApplicationTest.main(ApplicationTest.java:31)

其实很简单这个时候我们只需要在@Autowired注解中加上如下属性:

@Autowired(required=false)
private UserDao userDao;

再次运行测试类你会发现错误已经消失只是这个时候userDao是null如下:

实例bean为 === UserService [userDao=null]

2,@Qualifier注解的使用

把UserDao代码修改为如下:

import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
    // 给一个默认值
    private Integer version = 0;
    /**
     * 增加tostring方便测试
     */
    @Override
    public String toString() {
        return "UserDao [version=" + version + "]";
    }
    /**
     * @return the version
     */
    public Integer getVersion() {
        return version;
    }
    /**
     * @param version the version to set
     */
    public void setVersion(Integer version) {
        this.version = version;
    }
}

同时在配置类中增加一个@Bean的UserDao配置如下:

@Bean(value = "userDao2")
public UserDao getUserDao(){
        UserDao userDao = new UserDao();
        userDao.setVersion(2);
        return userDao;
}

运行测试类结果如下:

实例bean为 === UserService [userDao=UserDao [version=0]]

我们可以发现这个时候用的是默认的扫描到的UserDao,这个时候我们把UserService中注入的UserDao改成如下:

@Autowired(required=false)
private UserDao userDao2;

   继续运行测试类结果如下:

实例bean为 === UserService [userDao=UserDao [version=2]]

从以上运行结果我们可以发现如果有多个同类型的bean默认是根据对应的bean名称注入的,那如果这个时候我们不想使用spring默认的注入方式而是希望根据自己业务需要指定固定的bean,那就是@Qualifier注解表现的时候了如下:

@Qualifier(value="userDao")
@Autowired(required=false)
private UserDao userDao2;


这个时候不管你UserDao定义什么名字永远只会注入userDao这个bean了

3,@Primary注解的使用

不管是因为洁癖还是什么也好可能有些同学不是特别喜欢使用@Qualifier注解,那么没关系,spring还为我们提供了另外一个注解@Primary同样可以实现以上功能

假设现在我们UserService中注入的UserDao是userDao2,这么这个时候我们可以在配置类中的UserDao上增加@Primary注解如下:

@Primary
@Bean(value = "userDao2")
public UserDao getUserDao(){
        UserDao userDao = new UserDao();
        userDao.setVersion(2);
        return userDao;
}

这个时候运行测试类你会发现UserService注入的就是userDao2了

注意:这个时候UserService中的UserDao就不能再加@Qualifier对应的注解了



目录
相关文章
|
5月前
|
Java 测试技术 程序员
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring框架在日常开发中使用频繁,其依赖注入机制带来了极大的便利。然而,尽管@Autowired注解简化了依赖注入,Spring官方却不推荐在字段上使用它。本文将探讨字段注入的现状及其存在的问题,如难以进行单元测试、违反单一职责原则及易引发NPE等,并介绍为何Spring推荐构造器注入,包括增强代码可读性和维护性、方便单元测试以及避免NPE等问题。通过示例代码展示如何将字段注入重构为构造器注入,提高代码质量。
147 1
|
Java Spring 容器
|
9月前
|
Java Spring 容器
真的!@Autowired和@Resource注解使用的正确姿势,别再用错的了!
真的!@Autowired和@Resource注解使用的正确姿势,别再用错的了!
49 0
|
10月前
|
Java Spring 容器
同一接口有多个实现类,怎么来注入一个指定的实现?@Resource、@Autowired、@Qualifier
同一接口有多个实现类,怎么来注入一个指定的实现?@Resource、@Autowired、@Qualifier
528 0
|
10月前
|
安全 Java 开发者
Spring依赖注入大揭秘:@Autowired、@Qualifier和@Resource的区别与应用
Spring依赖注入大揭秘:@Autowired、@Qualifier和@Resource的区别与应用
414 0
|
Java Spring
【Java注解用法】@Autowired 与@Resource的区别以及@Qualifier的介绍
【Java注解用法】@Autowired 与@Resource的区别以及@Qualifier的介绍
112 0
|
Java Spring
解析Spring注解:@Resource与@Autowired的区别
在Spring框架中,依赖注入是实现松耦合、可维护性高的应用的重要方式之一。`@Resource`和`@Autowired`是两个常用的注解,用于实现依赖注入。然而,它们在用法和特点上有所不同。本文将详细介绍`@Resource`和`@Autowired`之间的区别,以及在Spring应用中的应用场景。
378 0
|
Java Spring 容器
Spring中的Autowired、Qualifier、Resource注解详解
使用Spring系列的框架对这三个注解肯定都不会陌生,这三个注解有一个特性,就是用于属性注入,说白了点就是将Spring容器中的对象取出来,这样我们才可以使用,那么这三者到底是什么关系,又有什么区别呢?
687 0
|
Java Spring 容器
请举例说明@Qualifier注解?
请举例说明@Qualifier注解?
请举例说明@Qualifier注解?