Spring注解:自动装配(@Autowired+@Qualifier+@Primary、@Resource、@Inject)
文章目录
一、概念
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
推荐阅读
-
两分钟学会自动注入@Resource和@Inject注解
-
两分钟学会自动注入@Resource和@Inject注解
-
Spring如何基于注解显式实现自动装配
-
Spring注解:自动装配(@Autowired+@Qualifier+@Primary、@Resource、@Inject)
-
Spring注解实现Bean自动装配示例详解
-
spring简单入门04 spring注解 spring自动装配
-
[Spring]手工装配之注解装配/@Resource/@Autowired/@Qualifier
-
4Spring自动装配——annotation resource方式
-
spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差异
-
Spring注解:自动装配(@Autowired+@Qualifier+@Primary、@Resource、@Inject)