在使用Spring進行項目開發的時候,會大量使用到自動裝配,那自動裝配是什么呢?簡單來說:Spring 利用依賴注入(DI)功能,完成SpringIOC容器中各個組件之間的依賴關系賦值管理。
下面介紹和總結可以在在Spring使用的三種自動注入的注解。首先回顧一下最初使用xml進行是如何進行注入的。
零、回顧:XML方式注入
使用 property 或者 constructor-arg 屬性。
<!-- 配置需要被Spring管理的Bean(創建,創建后放在了Spring IOC容器里面)--> <bean id="superMan" class="org.annotation.autowried.SuperMan"> <property name="car" ref="car"></property> <!--<constructor-arg ref="car"/>--> </bean> <bean id="car" class="org.annotation.autowried.Car"/>
public class SuperMan {
private Car car;
/* private SuperMan(Car car){
this.car = car;
}*/
public void setCar(Car car) {
this.car = car;
}
}
public class Car {
private String brand = "喇嘛殺敵";
}
這樣就能夠將需要的組件注入到Spring中,並且進行組件中的依賴關系管理。回顧結束,通過這種方式來,配置比較繁瑣,下面正式進入使用注解注入的主題。
@Autowired介紹
在Spring 2.5 引入了 @Autowired 注解!
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
從Autowired注解源碼上看,可以使用在下面這些地方:
@Target(ElementType.CONSTRUCTOR) #構造函數
@Target(ElementType.METHOD) #方法
@Target(ElementType.PARAMETER) #方法參數
@Target(ElementType.FIELD) #字段、枚舉的常量
@Target(ElementType.ANNOTATION_TYPE) #注解
還有一個value屬性,默認是true。
簡單總結:
1、@Autowired是Spring自帶的注解,通過AutowiredAnnotationBeanPostProcessor 類實現的依賴注入
2、@Autowired可以作用在CONSTRUCTOR、METHOD、PARAMETER、FIELD、ANNOTATION_TYPE
3、@Autowired默認是根據類型(byType )進行自動裝配的
4、如果有多個類型一樣的Bean候選者,需要指定按照名稱(byName )進行裝配,則需要配合@Qualifier。
指定名稱后,如果Spring IOC容器中沒有對應的組件bean拋出NoSuchBeanDefinitionException。也可以將@Autowired中required配置為false,如果配置為false之后,當沒有找到相應bean的時候,系統不會拋異常
簡單使用代碼:
在字段屬性上。
@Autowired
private HelloDao helloDao;
或者
private HelloDao helloDao;
public HelloDao getHelloDao() {
return helloDao;
}
@Autowired
public void setHelloDao(HelloDao helloDao) {
this.helloDao = helloDao;
}
或者
private HelloDao helloDao;
//@Autowired
public HelloServiceImpl(@Autowired HelloDao helloDao) {
this.helloDao = helloDao;
}
// 構造器注入也可不寫@Autowired,也可以注入成功。
將@Autowired寫在被注入的成員變量上,setter或者構造器上,就不用再xml文件中配置了。
如果有多個類型一樣的Bean候選者,則默認根據設定的屬性名稱進行獲取。如 HelloDao 在Spring中有 helloWorldDao 和 helloDao 兩個Bean候選者。
@Autowired
private HelloDao helloDao;
首先根據類型獲取,發現多個HelloDao,然后根據helloDao進行獲取,如果要獲取限定的其中一個候選者,結合@Qualifier進行注入。
@Autowired
@Qualifier("helloWorldDao")
private HelloDao helloDao;
注入名稱為helloWorldDao 的Bean組件。@Qualifier("XXX") 中的 XX是 Bean 的名稱,所以 @Autowired 和 @Qualifier 結合使用時,自動注入的策略就從 byType 轉變成 byName 了。
多個類型一樣的Bean候選者,也可以@Primary進行使用,設置首選的組件,也就是默認優先使用哪一個。
注意:使用@Qualifier 時候,如何設置的指定名稱的Bean不存在,則會拋出異常,如果防止拋出異常,可以使用:
@Qualifier("xxxxyyyy")
@Autowired(required = false)
private HelloDao helloDao;
在SpringBoot中也可以使用@Bean+@Autowired進行組件注入,將@Autowired加到參數上,其實也可以省略。
@Bean
public Person getPerson(@Autowired Car car){
return new Person();
}
// @Autowired 其實也可以省略
@Resource介紹
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
String name() default "";
// 其他省略
}
從Resource注解源碼上看,可以使用在下面這些地方:
@Target(ElementType.TYPE) #接口、類、枚舉、注解
@Target(ElementType.FIELD) #字段、枚舉的常量
@Target(ElementType.METHOD) #方法
name 指定注入指定名稱的組件。
簡單總結:
1、@Resource是JSR250規范的實現,在javax.annotation包下
2、@Resource可以作用TYPE、FIELD、METHOD上
3、@Resource是默認根據屬性名稱進行自動裝配的,如果有多個類型一樣的Bean候選者,則可以通過name進行指定進行注入
簡單使用代碼:
@Component
public class SuperMan {
@Resource
private Car car;
}
按照屬性名稱 car 注入容器中的組件。如果容器中BMW還有BYD兩種類型組件。指定加入BMW。如下代碼:
@Component
public class SuperMan {
@Resource(name = "BMW")
private Car car;
}
name 的作用類似 @Qualifier!
@Inject介紹
@Target({ METHOD, CONSTRUCTOR, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Inject {}
從Inject注解源碼上看,可以使用在下面這些地方:
@Target(ElementType.CONSTRUCTOR) #構造函數
@Target(ElementType.METHOD) #方法
@Target(ElementType.FIELD) #字段、枚舉的常量
簡單總結:
1、@Inject是JSR330 (Dependency Injection for Java)中的規范,需要導入javax.inject.Inject jar包 ,才能實現注入
2、@Inject可以作用CONSTRUCTOR、METHOD、FIELD上
3、@Inject是根據類型進行自動裝配的,如果需要按名稱進行裝配,則需要配合@Named;
簡單使用代碼:
@Inject
private Car car;
指定加入BMW組件。
@Inject
@Named("BMW")
private Car car;
@Named 的作用類似 @Qualifier!
總結
1、@Autowired是Spring自帶的,@Resource是JSR250規范實現的,@Inject是JSR330規范實現的
2、@Autowired、@Inject用法基本一樣,不同的是@Inject沒有一個request屬性
3、@Autowired、@Inject是默認按照類型匹配的,@Resource是按照名稱匹配的
4、@Autowired如果需要按照名稱匹配需要和@Qualifier一起使用,@Inject和@Name一起使用,@Resource則通過name進行指定