欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring注解:自动装配(@Autowired+@Qualifier+@Primary、@Resource、@Inject)

程序员文章站 2022-04-15 17:59:26
文章目录一、概念1.1 控制反转:lOC(Inversion Of Control)1.2 依赖注入:DI(Dependency Injection)1.3 自动装配二、前提三、@Autowired注解的使用3.1 @Autowired自动装配3.2 @Autowired+@Qualifier3.3 @Autowired+@Primary3.4 @Autowired细节3.4.1 其它用法3.4.2 @Autowired可以省略的两种情况四、@Resource和@Inject注解的使用4.1 @Resour...



一、概念

1.1 控制反转:lOC(Inversion Of Control)

主动式:要什么资源我们自己创建即可。过去采用的方式。

被动式:资源不是由我们自己创建,而是交给一个容器来创建和设置,我们直接拿来用。Spring采用的方式。

1.2 依赖注入:DI(Dependency Injection)

Spring中有个容器,容器能知道哪个组件(类)运行的时候,需要的另外一个组件(类)。容器通过反射的形式,将容器中准备好的组件注入当前组件中。

控制反转(IOC)是一种思想,依赖注入(DI)是一种实现。

1.3 自动装配

在传统的依赖注入配置中,我们必须要明确要给属性装配哪一个bean的引用,一旦bean很多,就不好维护了。

基于这样的场景,Spring使用注解进行自动装配,来解决这个问题。自动装配就是开发人员不必知道具体要装配哪个bean的引用,这个识别的工作会由Spring来完成。自动装配是为了将依赖注入“自动化”的一个简化配置的操作。


二、前提

首先要清楚组件(类)注册到Spring容器后的类型和name,方便下面的理解。

可以参考:https://blog.csdn.net/qq_42780289/article/details/107884738


三、@Autowired注解的使用

3.1 @Autowired自动装配

1)容器中同类型只有一个组件的情况

默认优先按照类型去容器中找对应的组件,找到就赋值。具体看下面的例子:

  • 组件1

    @Service public class BookService { } 

    类型为BookService,name为bookService。

  • 测试

     @Autowired BookService bookService; @Test void MyTest() { System.out.println(bookService); } 

    这里@Autowired先以属性的类型 BookService 去容器中找对应的组件,找到只有一个该类型的组件,成功!

2)容器中同类型有多个组件的情况

如果找到多个相同类型的组件,再将属性的名称作为组件的name去容器中查找。具体看下面的例子:

  • 组件1

    @Service public class BookService { } 

    类型为BookService,name为bookService。

  • 组件2

    @Configuration public class MainConfigOfAutowired { @Bean public BookService bookService01() { return new BookService(); } } 

    类型为BookService,name为bookService01。

  • 测试

     @Autowired BookService bookService; @Autowired BookService bookService01; @Test void MyTest() { System.out.println(bookService); System.out.println(bookService01); } 

    第一个@Autowired先以属性的类型 BookService 去容器中找对应的组件,找到有两个该类型的组件;接着将属性的名称 bookService 作为组件的name去容器中查找,找到组件1,成功!

    第二个@Autowired同理也可以找到组件2。

3)用类型和name都找不到组件

找不到就会报错。但是也可以使用@Autowired(required=false),找不到就赋值为空。

3.2 @Autowired+@Qualifier

使用@Qualifier指定需要装配的组件的name,而不是使用属性的类型或属性的名称。具体看下面的例子:

  • 组件1

    @Service public class BookService { } 

    类型为BookService,name为bookService。

  • 组件2

    @Configuration public class MainConfigOfAutowired { @Bean public BookService bookService01() { return new BookService(); } } 

    类型为BookService,name为bookService01。

  • 测试

     @Qualifier("bookService01") @Autowired BookService bookService; @Test void MyTest() { System.out.println(bookService); } 

    使用@Qualifier(“bookService01”)明确指定name后,@Autowired不再看属性的类型或属性的名称,直接用 bookService01 作为组件的name去容器中查找,找到组件2,成功!

3.3 @Autowired+@Primary

让Spring进行自动装配的时候,默认使用首选(用@Primary指定)的bean。具体看下面的例子:

  • 组件1

    @Service public class BookService { } 

    类型为BookService,name为bookService。

  • 组件2

    @Configuration public class MainConfigOfAutowired { @Primary @Bean public BookService bookService01() { return new BookService(); } } 

    类型为BookService,name为bookService01。

  • 测试1

     @Autowired BookService bookService; @Test void MyTest() { System.out.println(bookService); } 

    因为组件2使用了@Primary注解标注,所以@Autowired不再看属性的类型或属性的名称,直接就找到组件2,成功!

  • 测试2

     @Qualifier("bookService") @Autowired BookService bookService; @Test void MyTest() { System.out.println(bookService); } 

    虽然组件2使用了@Primary注解标注,但是使用@Qualifier()明确指定后,@Primary就不起作用了,所以还是直接用指定的 bookService 作为组件的name去容器中查找,找到组件1,成功!

3.4 @Autowired细节

3.4.1 其它用法

@Autowired可以标注在,构造器、参数、方法、属性上,都是从容器中获组件并赋值。

1)标注在属性上

上面已经谈论了很多,这里就不说了。

2)标注在方法上

@Component public class Bookshelf { private Book book; public Book getBook() { return book; } @Autowired public void setBook(Book book) { this.book = book; } } 

@Autowired标注在方法上,容器在创建 Bookshelf 对象时,会自动调用该方法从ioc容器中获取 Book 组件,注意该方法也会被执行一次。

3)标注在构造器上

@Component public class Bookshelf { private Book book; @Autowired public Bookshelf(Book book) { this.book = book; } public Book getBook() { return book; } public void setBook(Book book) { this.book = book; } } 

这里@Autowired标注在构造器上,容器在创建 Bookshelf 对象时,会先调用构造器从ioc容器中获取 Book 组件。

4)标注在参数上

@Configuration public class MyConfig { @Bean public Bookshelf bookshelf(@Autowired Book book) { return new Bookshelf(book); } } 

这里@Autowired标注在参数上,在向容器注册 Bookshelf 组件时要用到 Book 组件,所以会先从ioc容器中获取 Book 组件,再进行注册。

3.4.2 @Autowired可以省略的两种情况

1)标在构造器上的@Autowired可以省略

@Component
public class Bookshelf {
    private Book book;

    public Bookshelf(Book book) {
        this.book = book;
    }

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }
} 

如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,因为构造器要用的组件,都是从容器中获取。

2)@Bean标注方法时,参数的@Autowired可以省略

@Configuration public class MyConfig { @Bean public Bookshelf bookshelf(Book book) { return new Bookshelf(book); } } 

这里@Bean标注的方法注册组件的时候,方法参数的值可以直接从容器中获取。


四、@Resource和@Inject注解的使用

Spring还支持使用@Resource(JSR250)和@Inject(JSR330)。

4.1 @Resource自动装配

  • 可以和@Autowired一样可以实现自动装配功能。

  • 默认是按照属性的名称来进行装配的。也可以指定name,比如@Resource(name="")。

  • 没有类似@Autowired(reqiured=false)的功能,也不支持@Primary功能。

4.2 @Inject自动装配

  • 需要导入javax.inject的包。

    <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> 
  • 和@Autowired一样可以实现自动装配功能。

  • 和@Autowired一样,先按照属性的类型查找,如果有多个同类型的组件,再按照属性的名称进行查找。

  • 没有类似@Autowired(reqiured=false)的功能,但是支持@Primary功能。


五、总结

Spring支持使用@Autowired注解,也支持使用@Resource(JSR250)和@Inject(JSR330)注解。

其中@Autowired是Spring框架中的注解,而@Resource(JSR250)和@Inject(JSR330)是java规范的注解。三者的用法前面都有讲,@Autowired注解的功能是最强大的。

本文地址:https://blog.csdn.net/qq_42780289/article/details/107887896