介面簡介
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的呼叫機制。