@Autowired、@Inject、@Resource三者区别

@Autowired、@Inject、@Resource三者区别

一、@Autowired

  • @Autowired是spring自带的注解,通过 AutowiredAnnotationBeanPostProcessor 类实现的依赖注入;
  • @Autowired默认先按byType进行匹配,如果发现找到多个bean,则又按照byName方式(字段名)进行匹配(字段名与首字母小写的类名进行匹配,如果@Service指定了名称,则以指定的为准进行匹配),如果还可以匹配多个,则会报异常;
  • @Autowired有个属性为required,默认为true,如果配置为false之后,当没有找到相应bean的时候,系统不会报错;
  • @Autowired可以作用在变量、setter方法、构造函数上。
    @Autowired、@Inject、@Resource三者区别_第1张图片
  • 配合注解说明:
  1. @Qualifier(“XXX”) 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就只会按byName 了。
    不过需要注意的是@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。
    @Autowired、@Inject、@Resource三者区别_第2张图片
  2. @Primary,将该注解标注在被spring容器管理的bean上,告诉spring 在匹配多个bean时优先选择哪一个具体的实现来进行装配。

@Autowired 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类。

public interface Singer {
	String sing(String lyrics);
}

@Component("aSinger") // 加注解,让spring识别
public class ASinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "ASinger: "+lyrics;
    }
}

@Component // 方案三 改成@Component("singer")
//@Primary  //方案一
public class BSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "BSinger : "+lyrics;
    }
}

@Service
public class SingerService {
    
    @Autowired
    //@Qualifier("aSinger") //方案二(推荐使用)
    //private Singer aSinger; //方案四
    private Singer singer;

    public String sing(){
        return singer.sing("song lyrics");
    }
}

调用SingerService 类中的sing()方法会出现异常:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: aSinger,bSinger

原因:当一个接口存在多个实现类的话,Spring 根据类型无法选择到底注入哪一个,按singer属性名无法与对应的aSinger,bSinger匹配。
解决方案:

  1. 用@Primary 标注在一个实现类上,告诉spring 优先选择哪一个注入。
  2. 用@Qualifier标注在这个属性上,按指定名称进行匹配注入
  3. 指定被注入的类的名称和属性名一致,例如 @Service(“singer”)
  4. 将属性名改成被注入的类名首字母小写

二、@Resource

  • @Resource是JSR250规范的实现,需要导入javax.annotation实现注入。
  • @Resource默认根据名称进行自动装配,如果没有找到则按类型装配,一般会在@Resource中指定一个name属性或type属性,此时只会按照名称或类型进行匹配

@Resource装配顺序:
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

  • @Resource可以作用在变量、setter方法上。
    @Autowired、@Inject、@Resource三者区别_第3张图片

三、@Inject

  • @Inject是JSR330 (Dependency Injection for Java)中的规范,需要导入javax.inject.Inject;实现注入。

  • @Inject默认根据类型进行自动装配的,如果找到多个类型相同的,会按照名称进行匹配; 如果需要指定按照名称进行装配,则需要配合@Named;

  • @Inject可以作用在变量、setter方法、构造函数上。
    a、将@Inject可以作用在变量、setter方法、构造函数上,和@Autowired一样
    @Autowired、@Inject、@Resource三者区别_第4张图片

    b、@Named

  • @Named(“XXX”) 中的 XX是 Bean 的名称,所以 @Inject和 @Named结合使用时,自动注入的策略就从 byType 转变成 byName 了。
    @Autowired、@Inject、@Resource三者区别_第5张图片

总结:
1、@Autowired是spring自带的,@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,需要导入不同的包
2、@Autowired、@Inject用法基本一样,不同的是@Autowired有一个requried属性,装配的这个bean可以为null
3、@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
4、@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Named一起使用

你可能感兴趣的:(Spring,spring,java,spring,boot,bean)