zoukankan      html  css  js  c++  java
  • @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
  • 相关阅读:
    随笔列表--目录还没有时间来得及更改......
    [Redis] 万字长文带你总结Redis,助你面试升级打怪
    [Java] 多线程基础详细总结,附加详细实例
    这次,我是如何监控服务器CPU和内存的
    [Java][Web] Servlet中转发和重定向比较
    [Maven] Project build error: 'packaging' with value 'jar' is invalid. Aggregator projects require 'pom' as packaging.
    [JAVA][Liferay] Configure sharding in multiple sites
    [JAVA][Liferay] Duplicate key value violates unique constraint for resourcepermissionid in Liferay
    [Java][Liferay] 模拟用户
    [Java][Liferay] 如何从Javascript的function中获取language property的值
  • 原文地址:https://www.cnblogs.com/crelle/p/13721236.html
Copyright © 2011-2022 走看看