文章作者:Tyan
博客:noahsnail.com ?|? CSDN ?|? 簡書
3.9 基于注解的容器配置
在配置Spring時注解是否比XML更好?
基于注解配置的引入引出了一個問題——這種方式是否比基于XML的配置更好。簡短的回答是視情況而定。長一點的回答是每種方法都有它的優點和缺點,通常是由開發者決定哪一種策略更適合他們。由于注解的定義方式,注解在它們的聲明中提供了許多上下文,導致配置更簡短更簡潔。然而,XML擅長連接組件而不必接觸源代碼或重新編譯它們。一些開發者更喜歡接近源代碼,而另一些人則認為基于注解的類不再是POJOs,此外,配置變的去中心化,而且更難控制。
無論選擇是什么,Spring都能容納這兩種風格,甚至可以將它們混合在一起。值得指出的是,通過它的Java配置選項,Spring允許注解以一種非入侵的方式使用,不觸碰目標組件源碼和那些工具,所有的配置風格由Spring工具套件支持。
基于注解的配置提供了一種XML設置的可替代方式,它依賴于字節碼元數據來連接組件,而不是用尖括號聲明的方式。代替使用XML來描述bean連接,開發者通過將注解使用在相關的類,方法或字段聲明中,將配置移動到了組件類本身的內部。正如在“Example: The RequiredAnnotationBeanPostProcessor”那節提到的那樣,使用BeanPostProcessor
與注解結合是擴展Spring IoC容器的的常見方法。例如,Spring 2.0引入了@Required
注解來執行需要的屬性的可能性。Spring 2.5使以同樣地通用方法來驅動Spring的依賴注入變為可能。本質上來說,@Autowired
提供了如3.4.5小節描述的同樣的能力。“Autowiring collaborators”但更細粒度的控制和更廣的應用性。Spring 2.5也添加對JSR-250注解的支持,例如,@PostConstruct
和@PreDestroy
。Spring 3.0添加了對JSR-330,包含在javax.inject
包內的注解(Java的依賴注入)的支持,例如@Inject
和@Named
。關于這些注解的細節可以在相關的小節找到。
注解注入在XML注入之前進行,因此對于通過兩種方法進行組裝的屬性后者的配置會覆蓋前者。
跟以前一樣,你可以作為單獨的bean定義來注冊它們,但也可以通過在一個基于XML的Spring配置(注入包含上下文命名空間)中包含下面的標簽來隱式的注冊它們:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
(隱式注冊的后處理器包括 AutowiredAnnotationBeanPostProcessor
,CommonAnnotationBeanPostProcessor
,PersistenceAnnotationBeanPostProcessor
和前面提到的RequiredAnnotationBeanPostProcessor
。)
<context:annotation-config/>
僅在定義它的同樣的應用上下文中尋找注解的beans。這意味著,如果你在一個為DispatcherServlet
服務的WebApplicationContext
中放置了<context:annotation-config/>
,它只能在你的控制器中尋找@Autowired
注解的beans,而不是在你的服務層中。更多信息請看18.2小節,“The DispatcherServlet”。
3.9.1 @Required
@Required
注解應用到bean屬性的setter方法上,例子如下:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
這個注解僅僅是表明受影響的bean屬性必須在配置時通過顯式的bean定義或自動組裝填充。如果受影響的bean屬性沒有填充,容器會拋出一個異常,這允許及早明確的失敗,避免NullPointerExceptions
或后面出現類似的情況。仍然建議你在bean類本身加入斷言,例如,加入到初始化方法中。這樣做可以強制這些需要的引用和值,甚至是你在容器外部使用這個類的時候。
3.9.2 @Autowired
在下面的例子中JSR 330的
@Inject
注解可以用來代替Spring的@Autowired
注解。
你可以將@Autowired
注解應用到構造函數上。
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
從Spring框架4.3起,如果目標bena僅定義了一個構造函數,那么
@Autowired
注解的構造函數不再是必要的。如果一些構造函數是可獲得的,至少有一個必須要加上注解,以便于告訴容器使用哪一個。
正如預料的那樣,你也可以將@Autowired
注解應用到“傳統的”setter方法上:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
你也可以應用注解到具有任何名字和/或多個參數的方法上:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
你也可以應用@Autowired
到字段上,甚至可以與構造函數混合用:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
private MovieCatalog movieCatalog;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
通過給帶有數組的字段或方法添加@Autowired
注解,也可以從ApplicationContext
中提供一組特定類型的bean:
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
同樣也可以應用到具有同一類型的集合上:
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
如果你希望數組或列表中的項按指定順序排序,你的bean可以實現
org.springframework.core.Ordered
接口,或使用@Order
或標準@Priority
注解。
只要期望的key是String
,那么類型化的Maps就可以自動組裝。Map的值將包含所有期望類型的beans,key將包含對應的bean名字:
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
默認情況下,當沒有候選beans可獲得時,自動組裝會失敗;默認的行為是將注解的方法,構造函數和字段看作指明了需要的依賴。這個行為也可以通過下面的方式去改變。
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required=false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
每個類只有一個構造函數可以標記為必需的,但可以注解多個非必需的構造函數。在這種情況下,會考慮這些候選者中的每一個,Spring使用最貪婪的構造函數,即依賴最滿足的構造函數,具有最大數目的參數。
建議在
@Required
注解之上使用@Autowired
的required
特性。required
特性表明這個屬性自動裝配是不需要的,如果這個屬性不能被自動裝配,它會被忽略。另一方面@Required
是更強大的,在它強制這個屬性被任何容器支持的bean設置。如果沒有值注入,會拋出對應的異常。
你也可以對那些已知的具有可解析依賴的接口使用@Autowired
:BeanFactory
,ApplicationContext
,Environment
, ResourceLoader
,ApplicationEventPublisher
和MessageSource
。這些接口和它們的擴展接口,例如ConfigurableApplicationContext
或ResourcePatternResolver
,可以自動解析,不需要特別的設置。
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
@Autowired
,@Inject
,@Resource
和@Value
注解是通過SpringBeanPostProcessor
實現處理,這反過來意味著你不能在你自己的BeanPostProcessor
或BeanFactoryPostProcessor
中應用這些注解(如果有的話)。這些類型必須顯式的通過XML或使用Spring的@Bean
方法來'wired up'。
3.9.3 用@Primary微調基于注解的自動裝配
因為根據類型的自動裝配可能會導致多個候選目標,所以在選擇過程中進行更多的控制經常是有必要的。一種方式通過Spring的@Primary
注解來完成。當有個多個候選bean要組裝到一個單值的依賴時,@Primary
表明指定的bean應該具有更高的優先級。如果確定一個'primary' bean位于候選目標中間,它將是那個自動裝配的值。
假設我們具有如下配置,將firstMovieCatalog
定義為主要的MovieCatalog
。
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
根據這樣的配置,下面的MovieRecommender
將用firstMovieCatalog
進行自動裝配。
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
對應的bean定義如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog" primary="true">
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
3.9.4 微調基于注解且帶有限定符的自動裝配
當有多個實例需要確定一個主要的候選對象時,@Primary
是一種按類型自動裝配的有效方式。當需要在選擇過程中進行更多的控制時,可以使用Spring的@Qualifier
注解。為了給每個選擇一個特定的bean,你可以將限定符的值與特定的參數聯系在一起,減少類型匹配集合。在最簡單的情況下,這是一個純描述性值:
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
@Qualifier
注解也可以指定單個構造函數參數或方法參數:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main")MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
對應的bean定義如下。限定符值為"main"的bean被組裝到有相同值的構造函數參數中。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
對于回退匹配,bean名字被認為是默認的限定符值。因此你可以定義一個id為main
的bean來代替內嵌的限定符元素,會有同樣的匹配結果。然而,盡管你可以使用這個約定根據名字引用特定的beans,但是@Autowired
從根本上來講是使用可選的語義限定符來進行類型驅動注入的。這意味著限定符的值,即使回退到bean名稱,總是縮小語義類型匹配的集合;它們沒有從語義上將一個引用表達為一個唯一的bean id。好的限定符值是"main"或"EMEA"或"persistent",表達一個特定組件的性質,這個組件是獨立于bean id
的,即使前面例子中像這個bean一樣的匿名bean會自動生成id。
正如前面討論的那樣,限定符也可以應用到類型結合上,例如,Set<MovieCatalog>
。在這個例子中,根據聲明的限定符匹配的所有beans作為一個集合進行注入。這意味著限定符不必是唯一的;它們只是構成過濾標準。例如,你可以定義多個具有同樣限定符值"action"的MovieCatalog
,所有的這些都將注入到帶有注解@Qualifier("action")
的Set<MovieCatalog>
中。
如果你想通過名字表達注解驅動的注入,不要主要使用
@Autowired
,雖然在技術上能通過@Qualifier
值引用一個bean名字。作為可替代產品,可以使用JSR-250@Resource
注解,它在語義上被定義為通過組件唯一的名字來識別特定的目標組件,聲明的類型與匹配過程無關。@Autowired
有不同的語義:通過類型選擇候選beans,特定的String
限定符值被認為只在類型選擇的候選目標中,例如,在那些標記為具有相同限定符標簽的beans中匹配一個"account"限定符。
對于那些本身定義在集合/映射或數組類型中的beans來說,
@Resource
是一個很好的解決方案,適用于特定的集合或通過唯一名字區分的數組bean。也就是說,自Spring 4.3起,集合/映射和數組類型中也可以通過Spring的@Autowired
類型匹配算法進行匹配,只要元素類型信息在@Bean
中保留,返回類型簽名或集合繼承體系。在這種情況下,限定符值可以用來在相同類型的集合中選擇,正如在前一段中概括的那樣。
自Spring 4.3起,
@Autowired
也考慮自引用注入,例如,引用返回當前注入的bean。注意自注入是備用;普通對其它組件的依賴關系總是優先的。在這個意義上,自引用不參與普通的候選目標選擇,因此尤其是從不是主要的;恰恰相反,它們最終總是最低的優先級。在實踐中,自引用只是作為最后的手段,例如,通過bean的事務代理調用同一實例的其它方法:在考慮抽出受影響的方法來分隔代理bean的場景中。或者,使用@Resource
通過它的唯一名字可能得到一個返回當前bean的代理。
@Autowired
可以應用到字段,構造函數和多參數方法上,允許通過限定符注解在參數層面上縮減候選目標。相比之下,@Resource
僅支持字段和bean屬性的帶有單個參數的setter方法。因此,如果你的注入目標是一個構造函數或一個多參數的方法,堅持使用限定符。
你可以創建自己的定制限定符注解。簡單定義一個注解,在你自己的定義中提供@Qualifier
注解:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
然后你可以在自動裝配的字段和參數上提供定制的限定符:
public class MovieRecommender {
@Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
// ...
}
接下來,提供候選bean定義的信息。你可以添加<qualifier/>
標記作為<bean/>
標記的子元素,然后指定匹配你的定制限定符注解的類型和值。類型用來匹配注解的全限定類名稱。或者,如果沒有名稱沖突的風險,為了方便,你可以使用簡寫的類名稱。下面的例子證實了這些方法。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
在3.10小節,“類路徑掃描和管理組件”中,你將看到一個基于注解的替代方法,在XML中提供限定符元數據。特別地,看3.10.8小節,“用注解提供限定符元數據”。
在某些情況下,使用沒有值的注解就是足夠的。當注解為了通用的目的時,這是非常有用的,可以應用到跨幾個不同類型的依賴上。例如,當網絡不可用時,你可以提供一個要搜索的離線目錄。首先定義一個簡單的注解:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
然后將注解添加到要自動裝配的字段或屬性上:
public class MovieRecommender {
@Autowired
@Offline
private MovieCatalog offlineCatalog;
// ...
}
現在bean定義只需要一個限定符類型:
<bean class="example.SimpleMovieCatalog">
<qualifier type="Offline"/>
<!-- inject any dependencies required by this bean -->
</bean>
你也可以定義接收命名屬性之外的定制限定符注解或代替簡單的值屬性。如果要注入的字段或參數指定了多個屬性值,bean定義必須匹配所有的屬性值才會被認為是一個可自動裝配的候選目標。作為一個例子,考慮下面的注解定義:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}
這種情況下Format
是枚舉類型:
public enum Format {
VHS, DVD, BLURAY
}
要自動裝配的字段使用定制限定符進行注解,并且包含了兩個屬性值:genre
和format
。
public class MovieRecommender {
@Autowired
@MovieQualifier(format=Format.VHS, genre="Action")
private MovieCatalog actionVhsCatalog;
@Autowired
@MovieQualifier(format=Format.VHS, genre="Comedy")
private MovieCatalog comedyVhsCatalog;
@Autowired
@MovieQualifier(format=Format.DVD, genre="Action")
private MovieCatalog actionDvdCatalog;
@Autowired
@MovieQualifier(format=Format.BLURAY, genre="Comedy")
private MovieCatalog comedyBluRayCatalog;
// ...
}
最后,bean定義應該包含匹配的限定符值。這個例子也證實了bean元屬性可以用來代替<qualifier/>
子元素。如果可獲得<qualifier/>
,它和它的屬性優先級更高,如果當前沒有限定符,自動裝配機制會將<meta/>
內的值作為備用,正如下面的例子中的最后兩個bean定義。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Action"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Comedy"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="BLURAY"/>
<meta key="genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
</beans>
3.9.5 使用泛型作為自動裝配限定符
除了@Qualifier
注解外,也可以使用Java的泛型類型作為限定符的一種暗示方式。例如,假設你有如下配置:
@Configuration
public class MyConfiguration {
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
}
假設上面的beans實現了一個泛型接口,例如,Store<String>
和Store<Integer>
,你可以@Autowire
Store
接口,泛型將作為限定符使用:
@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
@Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean
當自動裝配Lists
,Maps
和Arrays
時,也會應用泛型限定符:
// 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;
3.9.6 CustomAutowireConfigurer
CustomAutowireConfigurer
是一個能使你注冊自己的定制限定符注解類型的BeanFactoryPostProcessor
,即使它們不使用Spring的@Qualifier
注解進行注解。
<bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
AutowireCandidateResolver
通過下面的方式決定自動裝配的候選目標:
每個bean定義的
autowire-candidate
在
<beans/>
元素可獲得的任何default-autowire-candidates
模式存在
@Qualifier
注解和任何在CustomAutowireConfigurer
中注冊的定制注解
當多個beans符合條件成為自動裝配的候選目標時,"primary" bean的決定如下:如果在候選目標中某個確定的bean中的primary
特性被設為true
,它將被選為目標bean。
3.9.7 @Resource
Spring也支持使用JSR-250 @Resource
對字段或bean屬性setter方法進行注入。這是在Java EE 5和6中的一種通用模式,例如在JSF 1.2管理的beans或JAX-WS 2.0的端點。Spring對它管理的對象也支持這種模式。
@Resource
采用名字屬性,默認情況下Spring將名字值作為要注入的bean的名字。換句話說,它遵循by-name語義,下面的例子證實了這一點:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
如果沒有顯式的指定名字,默認名字從字段名或setter方法中取得。在字段情況下,它采用字段名稱;在setter方法情況下,它采用bean的屬性名。因此下面的例子將名字為movieFinder
的bean注入到它的setter方法中:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
注解提供的名字被
CommonAnnotationBeanPostProcessor
感知的ApplicationContext
解析為bean名字。如果你顯式地配置了Spring的SimpleJndiBeanFactory
,名字會通過JNDI解析。但是建議你依賴默認行為,簡單使用Spring的JNDI查找功能保護間接查找級別。
在@Resource
特有的沒有顯式名字指定的情況下,類似于@Autowired
,@Resource
會進行主要的匹配類型來代替指定名字的bean并解析已知的可解析依賴:BeanFactory
,ApplicationContext
,ResourceLoader
,ApplicationEventPublisher
和MessageSource
接口。
因此在下面的例子中,customerPreferenceDao
字段首先查找名字為customerPreferenceDao
的bean,然后回退到主要的類型為CustomerPreferenceDao
的類型匹配。"context"字段會注入基于已知的可解析依賴類型ApplicationContext
。
public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
3.9.8 @PostConstruct和@PreDestroy
CommonAnnotationBeanPostProcessor
不僅識別@Resource
注解,而且識別JSR-250生命周期注解。在Spring 2.5引入了對這些注解的支持,也提供了在初始化回調函數和銷毀回調函數中描述的那些注解的一種可替代方式。假設CommonAnnotationBeanPostProcessor
在Spring的ApplicationContext
中注冊,執行這些注解的方法在生命周期的同一點被調用,作為對應的Spring生命周期接口方法或顯式聲明的回調方法。在下面的例子中,緩存會預先放置接近初始化之前,并在銷毀之前清除。
public class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
// populates the movie cache upon initialization...
}
@PreDestroy
public void clearMovieCache() {
// clears the movie cache upon destruction...
}
}
關于組合各種生命周期機制的影響的更多細節,請看“組合生命周期機制”小節。