接口簡介
BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 時對外暴露的擴展點,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實例化任何 bean 之前讀取 bean 的定義,並可以修改它。
BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的優先級,主要用來在常規的 BeanFactoryPostProcessor 檢測開始之前注冊其他 bean 定義。特別是,你可以通過 BeanDefinitionRegistryPostProcessor 來注冊一些常規的 BeanFactoryPostProcessor,因為此時所有常規的 BeanFactoryPostProcessor 都還沒開始被處理。
注意點:通過BeanDefinitionRegistryPostProcessor 注冊的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法將得不到調用,具體的原因會在下面的代碼中解釋。
BeanFactoryPostProcessor 接口調用機制
BeanFactoryPostProcessor 接口的調用在 AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
進入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 用於存放已經處理過的Bean名字
Set<String> processedBeans = new HashSet<>();
// 一般會進入這個判斷
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 所謂的regularPostProcessors就是指實現BeanFactoryPostProcessor接口的Bean
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 所謂的registryProcessors就是指實現BeanDefinitionRegistryPostProcessor接口的Bean
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 這邊遍歷的是通過ApplicationContext接口注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口
// 需要和BeanFactory中BeanDefinitionMap中的BeanFactoryPostProcessor接口區分開
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//如果是BeanDefinitionRegistryPostProcessor,則先進行postProcessBeanDefinitionRegistry處理,這個方法一般進行BeanDefinition注冊,從這邊可以看出BeanDefinitionRegistryPostProcessor接口的方法先調用,所以優先級高於BeanFactoryPostProcessor
// 通過這個代碼可以看出,通過ApplicationContext直接注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor並不支持Order接口,而是根據注冊的順序執行
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 保存這個BeanDefinitionRegistryPostProcessor,因為還要執行這個類的BeanFactoryPostProcessor方法;
registryProcessors.add(registryProcessor);
}
else {
// 保存,后面還要執行這個類的BeanFactoryPostProcessor方法;
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 這邊獲取的是BeanFactory中的BeanDefinitionRegistryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//先處理PriorityOrdered標注的BeanDefinitionRegistryPostProcessor
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//將其標記為已經處理,防止重復處理
processedBeans.add(ppName);
}
}
// 將其排序,以便按順序處理
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 將其保存,以便處理這個類的BeanFactoryPostProcessor方法
registryProcessors.addAll(currentRegistryProcessors);
// 執行BeanDefinitionRegistryPostProcessor接口方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清除,以便開始處理@Order標注的注解
currentRegistryProcessors.clear();
// 注意:這邊重新獲取BeanDefinitionRegistryPostProcessor是有深意的,因為上面在處理@PriorityOrdered標注的BeanDefinitionRegistryPostProcessor時可能又注入了新的BeanDefinitionRegistryPostProcessor。
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判斷是否處理過,防止重復處理,下面的邏輯和上面相同, 不介紹了
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 處理不標注注解的BeanDefinitionRegistryPostProcessor
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// 調用postProcessBeanFactory 方法,所以BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法的優先級要高。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 開始處理BeanFactoryPostProcessor接口
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 也是按照@PriorityOrdered @Ordered 和普通的方式進行處理
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 可能已經處理過
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
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(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 處理@Order標注的類
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
// 這邊通過名字重新拿了Bean,應該是怕上面的處理改變了Bean
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后調用普通的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
簡單總結
上面的方法看起來很長很復雜,但其實干的事情並不多,就調用了BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口的實現。這邊再簡單總結下具體的過程:
step1:執行通過ApplicationContext#addBeanFactoryPostProcessor()方法注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。
具體過程如下:假如通過ApplicationContext注冊了一個BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,那么會先執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,但是BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法和BeanFactoryPostProcessor的postProcessBeanFactory方法暫時都不會在這步執行。
另外需要注意的是:通過ApplicationContext注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都不支持@PriorityOrdered和@Ordered順序處理,而是按照我們添加的順序處理
step2:處理BeanFactory中的BeanDefinitionRegistryPostProcessor,處理的順序是先處理@PriorityOrdered標注的,再處理@Ordered標注的,最后處理普通的BeanDefinitionRegistryPostProcessor。到這邊,所有BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法都已經調用完畢,下面就開始處理BeanFactoryPostProcessor的postProcessBeanFactory方法。
step3:調用BeanDefinitionRegistryPostProcessor實現的postProcessBeanFactory方法(因為BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)
step4:調用通過ApplicationContext#addBeanFactoryPostProcessor()注冊的“單純”的BeanFactoryPostProcessor
step5:調用BeanFactory中的BeanFactoryPostProcessor,調用順序也是按照@PriorityOrdered和@Ordered順序處理,沒有這兩個注解的最后處理。
好了,到這邊BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口就已經處理完了。后面我們會拿ConfigurationClassPostProcessor 這個特殊的BeanDefinitionRegistryPostProcessor做列子講下具體流程,這邊只是介紹BeanFactoryPostProcessor的調用機制。