Spring IoC容器可以通過插入特殊的集成接口來實現(xiàn)拓展,而不需要繼承ApplicationContext的實現(xiàn)類。
1、BeanPostProcessor
org.springframework.beans.factory.config.BeanPostProcessor定義了回調(diào)方法,通過實現(xiàn)回調(diào)方法可以提供自己的實力話邏輯、依賴分析邏輯等。如果要在spring容器完成實例化、配置和初始化bean后,實例化一些自定義的邏輯,可以插入一個或多個BeanPostProcessor的實現(xiàn)。
我們可以配置多個BeanPostProcessor實例,也可以通過設(shè)置order屬性來控制這些BeanPostProcessor的執(zhí)行順序,還可以設(shè)置這個屬性僅作為BeanPostProcessor實現(xiàn)Ordered接口。如果編寫自己的BeanPostProcessor應(yīng)該考慮實現(xiàn)Ordered接口。

BeanPostProcessor接口定義了2個回調(diào)方法,當這樣的一個類注冊為容器的一個后置處理器時,由于每個bean實例都是由容器創(chuàng)建,這個后置處理器會在容器的初始化方法被調(diào)用前和任何bean實例化回調(diào)后從容器得到一個回調(diào)方法。后置處理器可以對bean采取任何措施,包括忽略回調(diào)。一個bean后置處理器,通常會檢查回調(diào)接口或使用代理包裝一個bean,部分AOP基礎(chǔ)設(shè)施類,為了提供包裝式的代理邏輯,倍實現(xiàn)為bean后置處理器。
ApplicationContext會自動檢測所有定義在配置元文件中,并實現(xiàn)了BeanPostProcessor接口的bean。ApplicationContext注冊這些bean作為后置處理器,使它們可以在bean創(chuàng)建完成后被調(diào)用,也可以像其他bean一樣被部署到容器中。
2、BeanFactoryPostProcessor
org.springframework.beans.factory.config.BeanFactoryPostProcessor接口與BeanPostProcessor類似,不同點是BeanFactoryPostProcessor操作bean的配置元數(shù)據(jù),即IoC容器允許BeanFactoryPostProcessor來讀取配置元數(shù)據(jù),并可以在容器實例化任何bean之前修改它。

我們可以配置多個BeanFactoryPostProcessor實例,也可以通過設(shè)置order屬性來控制這些BeanFactoryPostProcessor的執(zhí)行順序,還可以設(shè)置這個屬性僅作為BeanFactoryPostProcessor實現(xiàn)Ordered接口。如果編寫自己的BeanFactoryPostProcessor應(yīng)該考慮實現(xiàn)Ordered接口。
3、FactoryBean
org.springframework.beans.factory.FactoryBean接口的對象是它們自己的工廠,它是IoC容器實例化邏輯的棵插拔點。如果初始化代碼比較復(fù)雜,則相對于大量的XML來說,最好是使用Java來表達。我們可以創(chuàng)建自己的FactoryBean,在類中編寫復(fù)雜的初始化代碼,再將自定義的FactoryBean插入到容器中。

FactoryBean接口定義了三個方法:
getObject():返回工廠創(chuàng)建對象的實例,此實例是否被共享,取決于這個工廠返回的是單例還是原型實例。
getObjectType():返回由getObject()獲取的對象類型,或不知道類型時返回值為null。
isSingleton():若FactoryBean返回單例的實例,該方法返回true,否則返回false。
容器擴展示例:
PropertyPlaceholderConfigurer
PropertyPlaceholderConfigurer是BeanPostProcessor的一種實現(xiàn),它可以在標準的Properties格式的bean定義的分離文件中,用來具體化屬性值。這樣就允許應(yīng)用程序來自定義指定的環(huán)境屬性,如自定義數(shù)據(jù)庫連接信息,而無須修改容器的XML定義文件或其他文件。如下示例:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
? ? <property name="locations" values="classpath:jdbc.properties" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close">
? ??<property name="driverClassName" values="${jdbc.driverClassName}" />
? ??<property name="url" values="${jdbc.url}" />
????<property name="username" values="${jdbc.username}" />
????<property name="password" values="${jdbc.password}" />
</bean>
?jdbc.properties文件定義:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306
jdbc.username=root
jdbc.password=123456
dataSource的配置中使用了占位符來定義,從properties文件中獲取配置屬性。在運行時PropertyPlaceholderConfigurer會在bean定義的屬性中檢查占位符,然后匹配到properties中的鍵就會用其值替換${property-name}形式的占位符。spring2.5引入了context命名空間,可以使用專門的配置元素來配置屬性占位符。
<context:property-placeholder location="classpath:jdbc.properties" />
PropertyPlaceholderConfigurer不僅查看在Properties文件中指定的屬性,如果它不能在指定的屬性文件中找到屬性,也會檢查JavaSystem屬性,可以通過設(shè)置systemPropertiesMode屬性來定義行為:
1)never:從不檢查系統(tǒng)屬性。
2)fallback:如果沒有在指定的屬性文件中解析到屬性,就檢查系統(tǒng)屬性。
3)override:在檢查指定的屬性文件前,先去檢查系統(tǒng)屬性,允許系統(tǒng)屬性覆蓋其他任意的屬性資源。
PropertyOverrideConfigurer
PropertyOverrideConfigurer是BeanPostProcessor的另一種實現(xiàn),和PropertyPlaceholderConfigurer類似,它對于所有bean的屬性,原始定義可以有默認值或沒有值。如果一個Properties文件沒有特定bean的屬性配置項,就會使用默認的上下文定義。
由于bean定義是不知道被覆蓋的,因此從XML定義文件中并不能理解反映覆蓋配置文件被使用中。在多個PropertyOverrideConfigurer實例的情況下,為相同bean的屬性定義不同的值,只有最后一個有效,因其覆蓋機制導(dǎo)致的。
Properties屬性文件配置格式如下:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306
<context:property-override location="classpath:jdbc.properties" />
--參考文獻《Srping5開發(fā)大全》