在web開發中,我們經常會用到一些攔截器,比如Java Web中的filter,已經Spring MVC中的Interceptor,其能對一個請求進行前置與後置的處理。而在Spring中,可以使用BeanFactoryPostProcessor對BeanFactory進行攔截處理。
今天就來分析一下BeanFactoryPostProcessor對BeanFactory進行攔截處理的源碼。
其中 BeanFactoryPostProcessor 不是環繞攔截,而是 beanFactory 初始化完成之後的攔截。其接口源碼爲:
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) 註釋上寫到,此方法用來修改applicationContext內部已經創建好的beanFactory,此時所有的beanDefinition已經加載完成,但是還沒有任何bean被實際創建,此方法允許給未創建的bean修改或增加參數,比如修改其beanDefinition。
下面就來看一下 BeanFactoryPostProcessor 是如何來實現的,首先看一下ClassPathXmlApplicationContext 的初始化源碼:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 初始化 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
. . .
try {
. . .
// 此爲執行所有的 BeanFactoryPostProcessors
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
. .
// 此爲根據beanDefinition生成bean
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
}
. . .
}
}
可以看到,refresh()方法先生成了BeanFactory,生成BeanFactory過程中會使用BeanDefinitionReader來讀取所有的BeanDefinition,然後注入到BeanFactory中。
注入完成後,則會調用 invokeBeanFactoryPostProcessors(beanFactory) 來生成所有的BeanFactoryPostProcessors進行處理。
我們看一下 invokeBeanFactoryPostProcessors(beanFactory) 方法的源碼:
// 從 beanDefinition 中獲取到所有類型爲 BeanFactoryPostProcessor 的beanName列表
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
. . .
nonOrderedPostProcessorNames.add(ppName);
. . .
}
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
// 得到這些BeanFactoryPostProcessor 的 bean,其實就是直接創建。
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 執行其方法,傳入beanFactory
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
可以看到,我們先獲取到了所有 BeanFactoryPostProcessor 類型的beanName列表,然後根據beanName列表生成了bean列表,再遍歷bean列表對BeanFactory進行後置處理。