spring @Primary @Autowired @Qualifier 注解的使用户和区别

自我发现:我发现如果springboot中,我们重新定义某个bean,此bean的类型和名字都与底层本有的bean相同,这时候如果我们使用@Autowired注入,这是根据类型注入,有歧义,再加上@Qualifier注解指定名字,这时候因为底层本有的bean有一个ConditionalOnMissingBean的注解,其作用是如果容器中存在与自己同名的bean,自己就失效。所以自定义的bean,一加上根据名字来注入的注解(@Qualifier)声明的话,就算此时自定义的bean与底层本有的bean名字相同,容器也知道会注入自定义的bean,因为同名使底层本有的bean失效了。所以建议直接用@Resource声明。

 

@Autowired

在使用spring开发过程中,我们基本上都是使用 @Autowired 这个注解,用来注入已有的 bean。当 spring 中管理两个类型一样的 bean 时,再进行注入时会报错:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.pb.spring.Spring5AutowiredQualifierApplicationTests': Unsatisfied dependency expressed through field 'user3'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.pb.spring.domain.User' available: expected single matching bean but found 2: user1,getUser2
 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)

required 属性

@Autowired(required=true):当使用 @Autowired 注解的时候,其实默认就是@Autowired(required=true),表示注入的时候,该 bean 必须存在,否则就会注入失败。

@Autowired(required=false):表示忽略当前要注入的 bean,如果有直接注入,没有跳过,不会报错。

@Primary

看下面代码,@Primary 表示当遇到系统中有两个User类型时,优先使用 @Primary 注解的这个进行注入。

import com.pb.spring.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
 
@Configuration
public class UserConfig {
 
    @Bean(name = "user1")
    public User getUser1(){
        return new User("theodore",25);
    }
 
    @Primary
    @Bean(name = "user2")
    public User user2(){
        return new User("james",25);
    }
}
import com.pb.spring.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class Spring5AutowiredQualifierApplicationTests {
 
    @Autowired(required = false)  //一般在开发环境,不确定是否能注入时用
    private User user1;
 
    @Autowired
    @Qualifier(value = "user1")
    private User user2;
 
    @Autowired
    private User user3;
 
    @Test
    public void testAuto() {
        System.out.println(user2.getName());
        System.out.println(user1.getName());
        System.out.println(user3.getName());
    }
}

@Autowired:spring 中有两种注入方式,by type/by name,@Autowired 使用 byType 注入,当出现两个类型一样的时候,可以显示的用 @Qualifier 指定名称,表明用 by name 方式进行注入。否则会注入 @Primary 那个类。如果没有指定则会报错。 当不确定系统中是否能注入时,可以使用 required=false,不会强制注入。

@Resource

spring 不但支持自己定义的 @Autowired 注解,还支持几个由 JSR-250 规范定义的注解,它们分别是 @Resource、@PostConstruct 以及 @PreDestroy。
  @Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,而 @Resource 默认按 byName 自动注入罢了。@Resource 有两个属性是比较重要的,分是 name 和 type,Spring 将 @Resource 注解的name属性解析为 bean 的名字,而 type 属性则解析为 bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
  @Resource 装配顺序
  1. 如果同时指定了 name 和 type,则从 Spring 上下文中找到唯一匹配的 bean 进行装配,找不到则抛出异常
  2. 如果指定了 name,则从上下文中查找名称(id)匹配的 bean 进行装配,找不到则抛出异常
  3. 如果指定了 type,则从上下文中找到类型匹配的唯一 bean 进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定 name,又没有指定 type,则自动按照 byName 方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

@Autowired 与 @Resource的区别:

1、 @Autowired 与 @Resource 都可以用来装配 bean. 都可以写在字段上,或写在setter方法上。

2、 @Autowired 默认按类型装配(这个注解是属于 spring 的),默认情况下必须要求依赖对象必须存在,如果要允许 null 值,可以设置它的 required 属性为 false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合 @Qualifier 注解进行使用,如下:

@Autowired()@Qualifier("baseDao")
private BaseDao baseDao;

3、@Resource(这个注解属于 J2EE 的),默认按照名称进行装配,名称可以通过 name 属性进行指定,如果没有指定 name 属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在 setter 方法上默认取属性名进行装配。当找不到与名称匹配的 bean 时才按照类型进行装配。但是需要注意的是,如果 name 属性一旦指定,就只会按照名称进行装配。

@Resource(name="baseDao")
private BaseDao baseDao;

推荐使用:@Resource 注解在字段上,这样就不用写 setter 方法了,并且这个注解是属于 J2EE 的,减少了与 spring 的耦合。这样代码看起就比较优雅。


作者:theodore的技术提升之路
链接:https://www.jianshu.com/p/ba9ce8436678
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值