Spring的BeanFactoryPostProcessor介面

程式設計師自由之路發表於2021-02-24

介面簡介

BeanFactoryPostProcessor 介面是 Spring 初始化 BeanFactory 時對外暴露的擴充套件點,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器例項化任何 bean 之前讀取 bean 的定義,並可以修改它。

BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的優先順序,主要用來在常規的 BeanFactoryPostProcessor 檢測開始之前註冊其他 bean 定義。特別是,你可以通過 BeanDefinitionRegistryPostProcessor 來註冊一些常規的 BeanFactoryPostProcessor,因為此時所有常規的 BeanFactoryPostProcessor 都還沒開始被處理。

img

注意點:通過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的呼叫機制。

相關文章