当前位置: 移动技术网 > IT编程>开发语言>Java > Spring注解:自动装配(@Autowired+@Qualifier+@Primary、@Resource、@Inject)

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

2020年08月10日  | 移动技术网IT编程  | 我要评论



一、概念

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网