文章目錄
-
- @Required
- @Autowired
- @primary
- @Qualifier
- 泛型
- @Resource
- @PostConstruct和@PreDestroy
Spring的容器配置可以有兩種方式,一種基于XML檔案, 一種基于注解。注解注入在XML注入之前執行。是以,當兩個同時使用時,XML配置會覆寫注解注入的屬性。
本文會主要介紹 @Required,@Autowired, @PostConstruct, @PreDestroy 和 @Resource 這幾個注解。
這幾個注解都是由 context:annotation-config/ 來引入的。本質上引入這個配置會隐式的注冊AutoWiredAnnotationBeanPostProcessor(提供@Autowired),CommonAnnotationBeanPostProcessor(提供@PostConstruct, @PreDestroy, @Resource),RequiredAnnotationBeanPostProcessor(提供 @Required),進而提供各個注解的功能。
下面我們會分别介紹各個注解的功能。
@Required 一般用在方法上面,表示該方法的參數必須能通過配置或者自動裝載來填充。通常如果某個屬性是必須的,我們會使用這個注解。
不過從Spring Framework 5.1開始,@Required注解正式被棄用,取而代之的是使用構造函數注入用于所需的屬性,或使用InitializingBean.afterPropertiesSet()的自定義實作以及bean屬性setter方法。
示例代碼如下:
public class RequiredBean {
private BeanA beanA;
@Required
public void setBeanA(BeanA beanA){
this.beanA=beanA;
}
}
@Autowired 就是自動注入所需要的字段,參數等。JSR 330的@Inject注解可以代替spring的@Autowired注解。
你可以将@Autowired注解到構造器中,如下所示:
public class AutowiredBean {
private BeanA beanA;
@Autowired
public AutowiredBean(BeanA beanA){
this.beanA=beanA;
}
}
從SpringFramework4.3開始,如果目标bean隻定義了一個構造函數,那麼就不再需要在此類構造函數上使用@Autowired注解。但是,如果有多個構造函數可用,則必須至少對其中一個進行注解,以告訴容器使用哪一個。
@Autowired也可以注解到傳統的setter方法,如下例子所示:
public class AutowiredBean {
private BeanB beanB;
@Autowired
public void setBeanB(BeanB beanB){
this.beanB=beanB;
}
}
也可以把注解應用到任何名字和多個參數,如下所示:
@Autowired
public void configAB(BeanA beanA , BeanB beanB){
this.beanA=beanA;
this.beanB=beanB;
}
@Autowired也可以用在字段上,如下所示:
@Autowired
private BeanC beanC;
還可以通過将注解添加到需要該類型數組的字段或方法,那麼可以從ApplicationContext中擷取到該特定類型的所有bean,如下例所示:
@Autowired
private BeanC[] beanCList;
如果希望數組或清單中的項按特定順序排序,目标bean可以實作org.springframework.core.Ordered接口,或者可以使用@Order或标準的@Priority注解。
否則,它們的順序遵循容器中相應目标bean定義的注冊順序。
Map執行個體也可以被注入,隻要key是String類型。Map value包括了所有的類型比對的Bean,keys是該bean的名字。如下所示:
@Autowired
public void configMapA(Map<String,BeanA> mapA){
this.mapA=mapA;
}
@Autowired有個required屬性,如果要注入的bean有可能不存在,則可以如下所示:
@Autowired(required = false)
public void setBeanC(BeanC beanC){
}
建議使用@Autowired的’required’屬性而不是使用setter方法上的@Required注解。“required”屬性表示自動裝載需要該屬性, 如果無法自動裝載,則忽略該屬性。而對于@Required來說,如果未定義任何值,則會報異常。
也可以通過Java 8的java.util.Optional表示特定依賴項的非必需性質,如下示例顯示:
@Autowired
public void setMovieFinder(Optional<BeanC> BeanC) {
}
在Spring Framework 5.0中,你也可以使用@Nullable注解:
@Autowired
public void setMovieFinderC(@Nullable BeanC beanC) {
}
Spring可以使用@Autowired來自動解析一些預設存在的bean如:BeanFactory、ApplicationContext、Environment、ResourceLoader、ApplicationEventPublisher和MessageSource。這些接口及其擴充接口(如ConfigurableApplicationContext或ResourcePatternResolver)。
如下所示,自動注入ApplicationContext:
@Autowired
private ApplicationContext context;
注意: @Autowired, @Inject, @Value, 和 @Resource 注解是在Spring的BeanPostProcessor中處理的,這意味着你不能将這些注解用在你自己的BeanPostProcessor,BeanFactoryPostProcessor類型。
當按類型注入的時候,可能會有多個候選項,則可以通過@Primary注解表示優先的對象。如下所示:
@Configuration
public class ConfigBean {
@Bean
@Primary
public BeanA firstBeanA() { return new BeanA(); }
@Bean
public BeanA secondBeanA() { return new BeanA();}
}
@Primary是一種在多個執行個體中按類型使用自動裝載的有效方法,但是如果你希望對注入的Bean進行更細粒度的控制時候,可以使用@Qualifier。如下所示:
@Bean
@Qualifier("main")
public BeanC beanC() { return new BeanC();}
@Autowired
@Qualifier("main")
private BeanA beanA;
@Autowired
public void setBeanA(@Qualifier("main") BeanA beanA){
}
限定符的值并不是唯一的,它隻是一個過濾标準。
@Autowired一般用來通過類型比對,@Resource則是通過名稱比對。
也可以建立自定義注解:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
除了@Qualifier注解外,還可以使用Java泛型類型作為隐式的限定形式。例如,假設您具有以下配置:
public class StringStore implements Store<String> {
}
public class IntegerStore implements Store<Integer> {
}
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
public class GenericBean {
@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
@Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean
// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@Autowired
private List<Store<Integer>> s;
}
@Resource用在字段或者Setter方法上,預設情況下@Resource通過名字來注入。
public class ResourceBean {
@Resource(name = "beanA")
private BeanA BeanA;
}
如果未顯式指定名稱,則從字段名或setter方法派生預設名稱.
在@Resource用法中,如果沒有指定顯式名稱,并且類似于@Autowired,@Resource會找到一個主類型比對,而不是指定的bean,并解析已知的可解析依賴項:BeanFactory、ApplicationContext、ResourceLoader、ApplicationEventPublisher,和MessageSource接口。
這兩個注解主要用做生命周期回調。如下所示:
public class ConstructBean {
@PostConstruct
public void populateMovieCache() {
// populates the movie cache upon initialization...
}
@PreDestroy
public void clearMovieCache() {
// clears the movie cache upon destruction...
}
}
與@Resource一樣,@PostConstruct和@PreDestroy注解類型是JDK 6到8标準Java庫的一部分。然而,整個javax.annotation包與JDK 9中的核心Java子產品分離,并最終在JDK 11中被删除。如果需要,javax.annotation-api工件現在需要通過maven central獲得,隻需像其他庫一樣添加到應用程式的類路徑中即可。
- 區塊鍊從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特币等持續更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
- java程式員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程