@Autowired, @Inject 和@Resource的区别

我们可以使用下面三个注解来注入依赖项:

  • @Resource–在javax.annotation包中定义,此注释是JSR-250注释的一部分,与javaee一起打包。
  • @Inject–在javax.inject包中定义。为了访问@inject注解,javax.inject库必须声明为Maven依赖项。
  • @Autowired–在org.springframework.bean.factory包中定义,也是Spring框架的一部分。

@Autowired和@Inject注解的行为相同。这两个注解使用AutowiredAnnotationBeanPostProcessor注入依赖关系。

@Resource使用CommonAnnotationBeanPostProcessor注入依赖项。

执行的顺序

@Autowired和@Inject

    1. By Type匹配
    2. By Qualifier匹配
    3. By Name匹配

@Resource

    1. By Name匹配
    2. By Type匹配
    3. By Qualifier匹配(如果By Name找到匹配项,则忽略)

在下面的示例中,让我们看看这些注解是如何工作的。

这里,我们有Animal接口和两个实现Tiger和Lion。

Animal:

/**
 * @author:crelle
 * @className:Animal
 * @version:1.0.0
 * @date:2020/9/23
 * @description:XX
 **/
public interface Animal {

    String type();
}

Tiger:
import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:Tiger
 * @version:1.0.0
 * @date:2020/9/23
 * @description:XX
 **/
@Component
public class Tiger implements Animal {
    @Override
    public String type() {
        return "Tiger";
    }
}

Lion:

import org.springframework.stereotype.Component;

/**
 * @author:crelle
 * @className:Lion
 * @version:1.0.0
 * @date:2020/9/23
 * @description:XX
 **/
@Component
public class Lion implements Animal {
    @Override
    public String type() {
        return "Lion";
    }
}

场景1:接口类型(By Type)注入——使用@Resource或@Inject或@Autowired

AnimalKeeper1:

import org.springframework.beans.factory.annotation.Autowired;
import javax.inject.Inject;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author:crelle
 * @className:AnimalKeeper
 * @version:1.0.0
 * @date:2020/9/23
 * @description: cenario 1 : Inject using Interface type – Using @Resource or @Inject or @Autowired
 **/
@Component
public class AnimalKeeper1 {


      @Resource
private Animal animal; // @Inject // private Animal animal; // // @Autowired // private Animal animal; public Animal getAnimal() { return animal; } }
import crelle.test.springframework.beans.factory.annotation.annotationtypes.test1.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    private AnimalKeeper1 animalKeeper;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        System.out.println(animalKeeper.getAnimal().type());

    }
}

输出

Field animalKeeper in crelle.test.springframework.DemoApplication required a single bean, but 2 were found:
    - lion: defined in file [D:codingtry-new-technologiesspring-framework-test	argetclassescrelle	estspringframeworkeansfactoryannotationannotationtypes	est1Lion.class]
    - tiger: defined in file [D:codingtry-new-technologiesspring-framework-test	argetclassescrelle	estspringframeworkeansfactoryannotationannotationtypes	est1Tiger.class]

使用下面的注解也会给出上面的错误。

 @Inject
 private  Animal animal;


 @Autowired
 private  Animal animal;

所有的注解都在做同样的事情,即尝试By Type注入依赖项(Tiger和Lion). 因此Spring容器不知道要注入Tiger或者Lion,注入失败!

如果你确定要注入Tiger实现类,可以使用@Primary注解。

场景2:使用实例类型(By Type)作为具体类进行注入:-使用@Resource或@Inject或@Autowired

AnimalKeeper2:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.inject.Inject;

/**
 * @author:crelle
 * @className:AnimalKeeper1
 * @version:1.0.0
 * @date:2020/9/23
 * @description: Scenario 2 : Inject using field type as concrete class:- Using @Resource or @Inject or @Autowired
 **/
@Component
public class AnimalKeeper2 {

//    @Resource
//    private Tiger animal;

//     @Inject
//     private Tiger animal;

     @Autowired
     private Tiger animal;


    public Tiger getAnimal() {
        return animal;
    }
}
import crelle.test.springframework.beans.factory.annotation.annotationtypes.test1.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    private AnimalKeeper2 animalKeeper;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        System.out.println(animalKeeper.getAnimal().type());

    }
}

输出:

Tiger

所有的注解都得到了成功的注入。

原因-容器都在尝试By Type注入,而Animal的类型是具体的Tiger,所以注入没有歧义。

场景3:使用属性名称(By Name)注入:-使用@Resource或@Inject或@Autowired

AnimalKeeper3:

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author:crelle
 * @className:AnimalKeeper2
 * @version:1.0.0
 * @date:2020/9/23
 * @description: Scenario 3 : Injecting using field name:- Using @Resource or @Inject or @Autowired
 **/
@Component
public class AnimalKeeper3 {

    @Resource
    private Animal tiger;

    // @Inject
    // private Animal tiger;

    // @Autowired
    // private Animal tiger;


    public Animal getTiger() {
        return tiger;
    }
}
import crelle.test.springframework.beans.factory.annotation.annotationtypes.test1.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    private AnimalKeeper3 animalKeeper;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        System.out.println(animalKeeper.getTiger().type());

    }
}

输出:

Tiger

所有注解都将成功注入。

原因:它是按照属性名称(By Name)注入的,每当我们在类上使用@Component时,类名本身就会自动注册为spring bean。

Tiger类用Spring容器注册为tiger bean,而tiger bean是容器中唯一可用的类,因此没有歧义。

场景4:使用具有正确限定符名称(By Qualifier)注入:-使用@Resource或@Inject或@Autowired

AnimalKeeper4:

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author:crelle
 * @className:AnimalKeeper4
 * @version:1.0.0
 * @date:2020/9/23
 * @description: Scenario 4 : Using Qualifier with correct qualifier name:- Using @Resource or @Inject or @Autowired
 **/
@Component
public class AnimalKeeper4 {

    @Resource
    @Qualifier("tiger")
    private Animal animal;

    // @Inject
    // @Qualifier(“tiger”)
    // private Animal animal;

    // @Autowired
    // @Qualifier(“tiger”)
    // private Animal animal;


    public Animal getAnimal() {
        return animal;
    }
}
import crelle.test.springframework.beans.factory.annotation.annotationtypes.test1.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    private AnimalKeeper4 animalKeeper;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        System.out.println(animalKeeper.getAnimal().type());

    }
}

输出:

Tiger

所有注解都成功地注入了依赖bean。

原因:所有这些都是通过使用限定符名称(By Qualifier)tiger进行注入的,而容器中只有一个具有此名称的bean。

场景5:使用限定符名称不正确但字段名称正确的限定符(By Qualifier)

5.1 @Resource的行为将不同于@Inject和@Autowired

使用@Resource–此处By Name优先权大于By Qualifier

AnimalKeeper5_1:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author:crelle
 * @className:AnimalKeeper5
 * @version:1.0.0
 * @date:2020/9/23
 * @description: Scenario 5 : Using Qualifier with incorrect qualifier name , but with correct field name
 *                            Using @Resource – here Match by Name takes higher precedence.
 **/
@Component
public class AnimalKeeper5_1 {

@Resource
@Qualifier(value = "incorrect")
private Animal tiger;
public Animal getTiger() { return tiger; } 

}
import crelle.test.springframework.beans.factory.annotation.annotationtypes.test1.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    private AnimalKeeper5_1 animalKeeper;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        System.out.println(animalKeeper.getTiger().type());

    }
}

输出:

Tiger

5.2 使用@Inject或@Autowired:By Qualifier的优先权高于By Name。

AnimalKeeper5_2:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.inject.Inject;

/**
 * @author:crelle
 * @className:AnimalKeeper5_2
 * @version:1.0.0
 * @date:2020/9/23
 * @description: Using @Inject or @Autowired:Qualifier has higher precedence over field name.
 **/
@Component
public class AnimalKeeper5_2 {
    @Qualifier(value = "lion")
    @Autowired
    private Animal tiger;

// @Autowired
// @Qualifier(“incorrect”)
// private Animal tiger;

    public Animal getAnimal() {
        return tiger;
    }
}
import crelle.test.springframework.beans.factory.annotation.annotationtypes.test1.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    private AnimalKeeper5_2 animalKeeper;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        System.out.println(animalKeeper.getAnimal().type());

    }
}

输出

Lion
原文地址:https://www.cnblogs.com/crelle/p/13721236.html