Spring 原始碼學習 11:invokeBeanFactoryPostProcessors
前言
invokeBeanFactoryPostProcessors 會執行 BeanFactory 的後置處理器。看到這裡會有疑問:
- 什麼是 BeanFactoryPostProcessor ?
- BeanfactoryPostProcessor 該如何使用?
知道了上面兩個問題的答案,對 BeanFactoryPostProcessor 有了瞭解之後,然後再深入原始碼,繼續閱讀 invokeBeanFactoryPostProcessors 這個方法。
作用
資料還是在官網可以找到答案:
閱讀了一下,大概意思是 Spring IoC 容器允許 BeanFactoryPostProcessor 讀取配置元資料,並有可能在容器例項化除 BeanFactoryPostProcessor 例項以外的任何 bean 之前更改它。
同樣可以使用 Ordered 介面對 BeanFactoryPostProcessor 進行排序。
注意
BeanFactoryPostProcessor 操作的是 BeanDefinition ,即元資料。但是同樣可以通過獲取到 BeanFactory 進行例項化 Bean,但是官網很不建議這樣使用。
示例
使用 BeanFactoryPostProcessor
@Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 修改 BeanDefinition 資訊 BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent"); userComponentBeanDefinition.setLazyInit(true); // 修改 Bean 的資訊 // xxx 非常不推薦 beanFactory.getBean 過早的例項化 Bean UserComponent bean = beanFactory.getBean(UserComponent.class); bean.setUserName("liuzhihang-01"); } }
建立自己的 BeanFactoryPostProcessor 並實現 BeanFactoryPostProcessor 介面,添加註解即可。
當然除了實現 BeanFactoryPostProcessor 介面,還有其他介面可以實現:
使用 BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor 繼承了 BeanFactoryPostProcessor,同時擴充套件了增加了 postProcessBeanDefinitionRegistry
方法。可以支援在 BeanDefinition 註冊之後 Bean 例項化之前對 BeanDefinition 進行操作。
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改 BeanDefinition 資訊
BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
userComponentBeanDefinition.setLazyInit(true);
// 修改 Bean 的資訊
// xxx 非常不推薦 beanFactory.getBean 過早的例項化 Bean
UserComponent bean = beanFactory.getBean(UserComponent.class);
bean.setUserName("liuzhihang-01");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 註冊一個 BeanDefinition
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(OrderComponent.class);
AbstractBeanDefinition orderComponentBeanDefinition = builder.getBeanDefinition();
registry.registerBeanDefinition("orderComponent", orderComponentBeanDefinition);
}
}
下面是測試程式碼截圖:
OrderComponent 類沒有新增任何註解,然後註冊為 BeanDefinition 之後,從容器中可以獲取到 orderComponent。
如何修改欄位屬性
在 Spring 文件上說明,非常不建議在 BeanFactoryPostProcessor 中例項化 Bean,那這時候想修改 Bean 的資訊,改如何操作?
其實可以通過獲取到 MutablePropertyValues
後進行操作:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改 BeanDefinition 資訊
BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");
userComponentBeanDefinition.setLazyInit(true);
MutablePropertyValues userComponentPropertyValues = userComponentBeanDefinition.getPropertyValues();
userComponentPropertyValues.addPropertyValue("userName", "liuzhihang-02");
// 修改 Bean 的資訊
// xxx 非常不推薦 beanFactory.getBean 過早的例項化 Bean
// UserComponent bean = beanFactory.getBean(UserComponent.class);
// bean.setUserName("liuzhihang-01");
}
}
invokeBeanFactoryPostProcessors
看完前面,我想已經知道了 BeanFactoryPostProcessor 是做什麼用的了,而這一步的主要作用就是例項化所有的 BeanFactoryPostProcessor。
進入原始碼:
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 (!IN_NATIVE_IMAGE && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
其中 getBeanFactoryPostProcessors 方法獲取的是自己新增的 BeanFactoryPostProcessor。這句話是什麼意思呢?
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
看原始碼,就是直接從 beanFactoryPostProcessors 獲取的,那如何向其中新增呢?
其實呼叫容器的 addBeanFactoryPostProcessor
方法即可。
繼續閱讀重點程式碼 invokeBeanFactoryPostProcessors
:
注意注意,這塊程式碼非常長!
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// 判斷是否為 BeanDefinitionRegistry
// debug 發現 這裡傳入的是 DefaultListableBeanFactory
// DefaultListableBeanFactory 實現了 BeanDefinitionRegistry
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 建立了兩個 List 集合, 用來存放處理器
// BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子介面
// BeanDefinitionRegistryPostProcessor 還可以額外處理 BeanDefinition, 新增 BeanDefinition
// 用法可以參考示例
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 迴圈 beanFactoryPostProcessors
// beanFactoryPostProcessors 是使用 API context.addBeanFactoryPostProcessor 新增進來的
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// BeanDefinitionRegistryPostProcessor 要單獨新增到 registryProcessors
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 處理 Bean 的資訊
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 上面迴圈是執行的我們呼叫 API 新增的 BeanDefinitionRegistryPostProcessor
// 下面執行 Spring 自己的 BeanDefinitionRegistryPostProcessor 集合
// 先執行實現了 PriorityOrdered介面的,然後是 Ordered 介面的,最後執行剩下的
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 第一步先呼叫 BeanDefinitionRegistryPostProcessors 它實現了PriorityOrdered
// 在初始化 reader 時 在註冊了 ConfigurationClassPostProcessor 到容器裡面
// BeanDefinitionRegistryPostProcessor 實現了 BeanDefinitionRegistryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 新增 bean
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 這裡只添加了名字 後面用來判斷誰已經執行過了
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 迴圈執行 processors 的 postProcessBeanDefinitionRegistry 方法
// 這個得在仔細看
// debug 看到 執行完這一步我另一個加 @Component 註解的類 註冊到 Registry 裡面了
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 清除
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 處理實現 Ordered 的 processor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 只有不包含的才執行, 執行完之後會新增進 processedBeans
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, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最後執行其他
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 只有不包含的才執行, 執行完之後會新增進 processedBeans
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, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 上面處理的都是 postProcessBeanDefinitionRegistry 是在 -> BeanDefinitionRegistryPostProcessor 中
// 下面開始處理 postProcessBeanFactory -> 是在 BeanFactoryPostProcessor 中
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// Invoke factory processors registered with the context instance.
// 不是 BeanDefinitionRegistry 則是普通 BeanFactory 直接執行 beanFactoryPostProcessors 即可
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 第二部分
// 上面執行的是 BeanDefinitionRegistryPostProcessor
// 下面開始執行 BeanFactoryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 按照順序執行
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);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 執行實現 PriorityOrdered 的
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
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();
}
上面總體可以分為兩部分:
- 執行 BeanDefinitionRegistryPostProcessor 接口裡面的兩個方法:postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。
- 執行 BeanFactoryPostProcessor 接口裡面的 postProcessBeanFactory 方法。
以第一部分為例:
- 首先判斷傳入的 BeanFactory 是否為 BeanDefinitionRegistry
- 宣告兩個 List 集合,regularPostProcessors 用來儲存 BeanFactoryPostProcessor,registryProcessors 用來儲存 BeanDefinitionRegistryPostProcessor
- 迴圈 beanFactoryPostProcessors,這個就是我們使用 API 方式新增進來的 BeanFactoryPostProcessor。
- 在迴圈中 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 會被執行,也就是說我示例的那個新增 BeanDefinition 演示的方法會被執行。
- 開始執行 Spring 自己的 BeanDefinitionRegistryPostProcessor, 處理順序為 PriorityOrdered, Ordered, and the rest
- 迴圈,將對應的 BeanDefinitionRegistryPostProcessor 新增到 currentRegistryProcessors 集合和processedBeans集合表示為已經處理。
- 排序後新增到第一步的 registryProcessors 中。
- 呼叫 invokeBeanDefinitionRegistryPostProcessors 執行所有的 Processor 裡面的 postProcessBeanDefinitionRegistry 方法
- 執行完 1 和 2 之後,所有的 postProcessBeanDefinitionRegistry 已經被執行完了,但是兩個集合(registryProcessors、regularPostProcessors)裡面的 postProcessBeanFactory 方法還沒有被執行。最後會迴圈執行。
- 宣告兩個 List 集合,regularPostProcessors 用來儲存 BeanFactoryPostProcessor,registryProcessors 用來儲存 BeanDefinitionRegistryPostProcessor
- 如果不是 BeanDefinitionRegistry 型別,則直接執行傳入的 beanFactoryPostProcessors 即可。
下面是對應的程式碼截圖
以上只是這個方法的前半部分,執行了 BeanDefinitionRegistryPostProcessor 裡面的 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。
因為還有直接實現 BeanFactoryPostProcessor 的處理器,下面則開始處理 BeanFactoryPostProcessor 的處理器。過程和上面類似。
總結
通過以上的閱讀,對 invokeBeanFactoryPostProcessors(beanFactory);
這一步方法進行總結。
BeanFactoryPostProcessor 作用
BeanFactoryPostProcessor 主要作用是在註冊 BeanDefinition 之後,在 Bean 初始化之前,修改 BeanDefinition 的資訊。
BeanFactoryPostProcessor 有個實現叫 BeanDefinitionRegistryPostProcessor,它可以額外的註冊新的 BeanDefinition 到容器中。
流程概述
- 這一步主要是處理 BeanFactoryPostProcessor,分為兩步。
- 執行 BeanDefinitionRegistryPostProcessor 接口裡面的兩個方法:postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。
- 執行 BeanFactoryPostProcessor 接口裡面的 postProcessBeanFactory 方法。