工廠處理器是一種特殊的Bean,這種Bean並不對外提供服務,它甚至可以無需id屬性,它主要負責對容器本身進行某些特殊的處理。Spring中有兩類工廠後處理器,一個是BeanFactoryPostProcessor,它是所有工廠後處理器的頂層接口;另一個是BeanDefinitionRegistryPostProcessor,它繼承自BeanFactoryPostProcessor,設計它的目的是使用它向Bean註冊表(一個BeanDefinitionRegistry 對象)中註冊bean的配置信息——一個BeanDefinition對象。
BeanFactoryPostProcessor的定義
Spring工廠後處理器的頂層接口org.springframework.beans.factory.config.BeanFactoryPostProcessor的定義如下。
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
postProcessBeanFactory方法在BeanFactory對象實例化完成後,當所有的bean的BeanDefinition對象加載完成時(即,所有bean的配置信息都已經註冊到bean註冊表中)被調用。它允許覆蓋或者設置bean的屬性值,甚至是立即實例化bean,比如實例化bean後處理器對象。
BeanDefinitionRegistryPostProcessor的定義
Spring還定義了一個工廠後處理器接口,那就是org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor,該接口繼承了BeanFactoryPostProcessor。下面是它的源碼定義。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
postProcessBeanDefinitionRegistry方法用向bean註冊表BeanDefinitionRegistry對象(一般是Spring默認的BeanFacotry對象——DefaultListableBeanFactory)中註冊bean的配置信息,即註冊BeanDefintion對象。
兩類工廠bean的執行順序
BeanFactoryPostProcessor的postProcessBeanFactory方法在所有的bean的BeanDefinition對象加載到bean註冊表中後被調用,而BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法用於向bean註冊表中註冊BeanDefinition對象。因此,這兩個方法的執行順序有嚴格的要求,下面我們通過Spring4的源碼解釋這個流程。
Spring4執行把通過PostProcessorRegistrationDelegate的靜態方法invokeBeanFactoryPostProcessors方法執行工廠後處理器的相關方法,此方法的代碼如下。(這段代碼有點長,看我的註釋就是了)
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 首先執行BeanDefinitionRegistryPostProcessors
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
// 遍歷容器中的工廠後處理器
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 執行BeanDefinitionRegistryPostProcessor的
// ->postProcessBeanDefinitionRegistry方法
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// 獲取並執行bean工廠中定義的BeanDefinitionRegistryPostProcessor對象,這裏分爲三步,如下。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 首先,執行實現了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor對象
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// 然後,執行實現了Ordered接口的BeanDefinitionRegistryPostProcessor對象
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registryPostProcessors.addAll(orderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
// 最後執行其它的BeanDefinitionRegistryPostProcessor對象
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
registryPostProcessors.add(pp);
processedBeans.add(ppName);
pp.postProcessBeanDefinitionRegistry(registry);
reiterate = true;
}
}
}
// 執行BeanDefinitionRegistryPostProcessor工廠後處理器的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
// 執行容器中普通的工廠後處理器的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// 執行容器中的bean工廠後處理器的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 獲取定義在bean工廠中的bean工廠後處理器,下面執行postProcessBeanFactory方法也分成三步,如下。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 把bean工廠後處理器按PriorityOrdered、Ordered和其他來分類
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// 排除前面已經執行了的後處理器
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先執行實現了PriorityOrdered接口的後處理器
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 然後執行實現了Ordered接口的後處理器
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最後執行其他的後處理器
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清除工廠中的元數據緩存
beanFactory.clearMetadataCache();
}
/**
* 執行給定的BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
/**
* 執行給定的bean工廠
**/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
上面的執行流程用圖表達如下。
上圖很明顯的表達了bean工廠後處理器的執行順序,但這裏還有兩點需要說明的。
a. 爲什麼要先執行BeanDefinitionRegistryPostProcessor?因爲實現BeanDefinitionRegistryPostProcessor 接口的後處理器可以在bean工廠創建其他bean之前添加更多的BeanDefinition對象到bean工廠中去。比如spring中ConfigurationClassPostProcessor類就是這樣一種工廠後處理器,它主要把被@Configuration註解的類中定義的bean信息轉換成BeanDefinition對象,並註冊到bean工廠中。
b. 這個流程中有一個很明顯的規定就是,不管是什麼工廠後處理器,都必須先執行容器中的工廠後處理器後,才執行bean工廠中的工廠後處理器。這裏的容器中的工廠後處理器是指ApplicationContext對象所持有的未註冊到bean工廠中的。bean工廠中的工廠後處理器是指註冊到BeanFactory對象中的後處理器。
BeanDefinitionRegistryPostProcessor接口的實現類
spring-context-x.x.x模塊下的org.springframework.context.annotation.ConfigurationClassPostProcessor後處理器,用於加載基於java類配置的bean。
mybatis-spring包中的org.mybatis.spring.mapper.MapperScannerConfigurer:用於掃描指定包下的mapper接口。
BeanFactoryPostProcessor接口的實現類
spring-beans-x.x.x模塊下的PropertyOverrideConfigurer:加載屬性文件中信息直接覆蓋Spring配置文件中的元數據。
spring-beans-x.x.x模塊下PropertyPlaceholderConfigurer及其子類PreferencesPlaceholderConfigurer:負責讀取properties屬性文件裏的屬性值,並將這些屬性值設置成Spring配置文件的元數據。
spring-context-x.x.x模塊下PropertySourcesPlaceholderConfigurer:和PropertyPlaceholderConfigurer的作用一樣,不過前者是spring3.1後<context:property-placeholder/>默認加載。後者是3.1以前默認加載的。
關於上面3個與加載屬性文件相關的後處理器如何被引入到Spring容器中,請見解析context命名空間之property-placeholder和property-override標籤
spring-beans-x.x.x模塊下的CustomScopeConfigurer:用於向BeanFactory中註冊自定義bean作用域Scope對象。
spring-beans-x.x.x模塊下的CustomEditorConfigurer:用於向BeanFactory中註冊自定義的PropertyEditorRegistrar對象和PropertyEditor對象。