最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring的BeanFactoryPostProcessor接口示例代碼詳解

 更新時間:2021年02月24日 14:11:48   作者:程序員自由之路  
這篇文章主要介紹了Spring的BeanFactoryPostProcessor接口,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

接口簡介

BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 時對外暴露的擴展點,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實例化任何 bean 之前讀取 bean 的定義,并可以修改它。

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

注意點:通過BeanDefinitionRegistryPostProcessor 注冊的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法將得不到調(diào)用,具體的原因會在下面的代碼中解釋。

BeanFactoryPostProcessor 接口調(diào)用機制

BeanFactoryPostProcessor 接口的調(diào)用在 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) {
   // 用于存放已經(jīng)處理過的Bean名字
		Set<String> processedBeans = new HashSet<>();
   // 一般會進入這個判斷
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    // 所謂的regularPostProcessors就是指實現(xiàn)BeanFactoryPostProcessor接口的Bean
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    // 所謂的registryProcessors就是指實現(xiàn)BeanDefinitionRegistryPostProcessor接口的Bean
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    // 這邊遍歷的是通過ApplicationContext接口注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口
    // 需要和BeanFactory中BeanDefinitionMap中的BeanFactoryPostProcessor接口區(qū)分開
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
      //如果是BeanDefinitionRegistryPostProcessor,則先進行postProcessBeanDefinitionRegistry處理,這個方法一般進行BeanDefinition注冊,從這邊可以看出BeanDefinitionRegistryPostProcessor接口的方法先調(diào)用,所以優(yōu)先級高于BeanFactoryPostProcessor
      // 通過這個代碼可以看出,通過ApplicationContext直接注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor并不支持Order接口,而是根據(jù)注冊的順序執(zhí)行
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
      // 保存這個BeanDefinitionRegistryPostProcessor,因為還要執(zhí)行這個類的BeanFactoryPostProcessor方法;
					registryProcessors.add(registryProcessor);
				}
				else {
      // 保存,后面還要執(zhí)行這個類的BeanFactoryPostProcessor方法;
					regularPostProcessors.add(postProcessor);
				}
			}

			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    // 這邊獲取的是BeanFactory中的BeanDefinitionRegistryPostProcessor
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
     //先處理PriorityOrdered標(biāo)注的BeanDefinitionRegistryPostProcessor
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
      //將其標(biāo)記為已經(jīng)處理,防止重復(fù)處理
					processedBeans.add(ppName);
				}
			}
    // 將其排序,以便按順序處理
			sortPostProcessors(currentRegistryProcessors, beanFactory);
    // 將其保存,以便處理這個類的BeanFactoryPostProcessor方法
			registryProcessors.addAll(currentRegistryProcessors);
    // 執(zhí)行BeanDefinitionRegistryPostProcessor接口方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    // 清除,以便開始處理@Order標(biāo)注的注解
			currentRegistryProcessors.clear();
  
    // 注意:這邊重新獲取BeanDefinitionRegistryPostProcessor是有深意的,因為上面在處理@PriorityOrdered標(biāo)注的BeanDefinitionRegistryPostProcessor時可能又注入了新的BeanDefinitionRegistryPostProcessor。
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
     // 判斷是否處理過,防止重復(fù)處理,下面的邏輯和上面相同, 不介紹了
				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();

    // 處理不標(biāo)注注解的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();
			}

			// 調(diào)用postProcessBeanFactory 方法,所以BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法的優(yōu)先級要高。
			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) {
    // 可能已經(jīng)處理過
			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);
			}
		}
   // 先執(zhí)行@PriorityOrdered標(biāo)注的接口
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
   // 處理@Order標(biāo)注的類
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
    // 這邊通過名字重新拿了Bean,應(yīng)該是怕上面的處理改變了Bean
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 最后調(diào)用普通的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();
	}

簡單總結(jié)

上面的方法看起來很長很復(fù)雜,但其實干的事情并不多,就調(diào)用了BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口的實現(xiàn)。這邊再簡單總結(jié)下具體的過程:

step1:執(zhí)行通過ApplicationContext#addBeanFactoryPostProcessor()方法注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。

具體過程如下:假如通過ApplicationContext注冊了一個BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,那么會先執(zhí)行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,但是BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法和BeanFactoryPostProcessor的postProcessBeanFactory方法暫時都不會在這步執(zhí)行。

另外需要注意的是:通過ApplicationContext注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都不支持@PriorityOrdered和@Ordered順序處理,而是按照我們添加的順序處理

step2:處理BeanFactory中的BeanDefinitionRegistryPostProcessor,處理的順序是先處理@PriorityOrdered標(biāo)注的,再處理@Ordered標(biāo)注的,最后處理普通的BeanDefinitionRegistryPostProcessor。到這邊,所有BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法都已經(jīng)調(diào)用完畢,下面就開始處理BeanFactoryPostProcessor的postProcessBeanFactory方法。

step3:調(diào)用BeanDefinitionRegistryPostProcessor實現(xiàn)的postProcessBeanFactory方法(因為BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)

step4:調(diào)用通過ApplicationContext#addBeanFactoryPostProcessor()注冊的“單純”的BeanFactoryPostProcessor

step5:調(diào)用BeanFactory中的BeanFactoryPostProcessor,調(diào)用順序也是按照@PriorityOrdered和@Ordered順序處理,沒有這兩個注解的最后處理。

好了,到這邊BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口就已經(jīng)處理完了。后面我們會拿ConfigurationClassPostProcessor 這個特殊的BeanDefinitionRegistryPostProcessor做列子講下具體流程,這邊只是介紹BeanFactoryPostProcessor的調(diào)用機制。

到此這篇關(guān)于Spring的BeanFactoryPostProcessor接口的文章就介紹到這了,更多相關(guān)Spring BeanFactoryPostProcessor接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳細講解Java輸入語句的寫法

    詳細講解Java輸入語句的寫法

    作為初步進入java開發(fā)學(xué)習(xí)的小白來說,學(xué)習(xí)java語言一開始的時候得一步步的學(xué)習(xí),比如說java輸入語句應(yīng)該這么去實現(xiàn)呢,這篇文章主要給大家介紹了關(guān)于Java輸入語句的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • 徹底解決java.lang.ClassNotFoundException: com.mysql.jdbc.Driver問題

    徹底解決java.lang.ClassNotFoundException: com.mysql.jdbc.Dr

    這篇文章給大家介紹了如如何徹底解決java.lang.ClassNotFoundException: com.mysql.jdbc.Driver問題,文中有詳細的解決思路以及解決方法,需要的朋友可以參考下
    2023-11-11
  • Java中簡單實用Quartz概述

    Java中簡單實用Quartz概述

    Quartz是一個開源的Java調(diào)度框架,可以用來實現(xiàn)在指定的時間或時間間隔觸發(fā)任務(wù)執(zhí)行的功能,這篇文章主要介紹了Java中簡單實用Quartz,需要的朋友可以參考下
    2023-02-02
  • SpringBoot3中數(shù)據(jù)庫集成實踐詳解

    SpringBoot3中數(shù)據(jù)庫集成實踐詳解

    項目工程中,集成數(shù)據(jù)庫實現(xiàn)對數(shù)據(jù)的增曬改查管理,是最基礎(chǔ)的能力,所以下面小編就來和大家講講SpringBoot3如何實現(xiàn)數(shù)據(jù)庫集成,需要的可以參考下
    2023-08-08
  • java 發(fā)送http和https請求的實例

    java 發(fā)送http和https請求的實例

    下面小編就為大家分享一篇java 發(fā)送http和https請求的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • 解決lombok 父類和子類builder不兼容的問題

    解決lombok 父類和子類builder不兼容的問題

    這篇文章主要介紹了解決lombok 父類和子類builder不兼容的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Java中Array、List、ArrayList的區(qū)別及說明

    Java中Array、List、ArrayList的區(qū)別及說明

    這篇文章主要介紹了Java中Array、List、ArrayList的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java中使用數(shù)組實現(xiàn)棧數(shù)據(jù)結(jié)構(gòu)實例

    Java中使用數(shù)組實現(xiàn)棧數(shù)據(jù)結(jié)構(gòu)實例

    這篇文章主要介紹了Java中使用數(shù)組實現(xiàn)棧數(shù)據(jù)結(jié)構(gòu)實例,本文先是講解了實現(xiàn)棧至少應(yīng)該包括以下幾個方法等知識,然后給出代碼實例,需要的朋友可以參考下
    2015-01-01
  • logback過濾部分日志輸出的操作

    logback過濾部分日志輸出的操作

    這篇文章主要介紹了logback過濾部分日志輸出的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • maven <repositories>標(biāo)簽和<pluginRepositories>標(biāo)簽的使用

    maven <repositories>標(biāo)簽和<pluginRepositories>標(biāo)簽的使用

    這篇文章主要介紹了maven <repositories>標(biāo)簽和<pluginRepositories>標(biāo)簽的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07

最新評論

封丘县| 扬中市| 松滋市| 天峨县| 阳曲县| 星座| 康定县| 日土县| 微博| 合水县| 达州市| 曲阜市| 仲巴县| 大港区| 仲巴县| 云南省| 乃东县| 浠水县| 峡江县| 武功县| 辽阳市| 麦盖提县| 富顺县| 阳曲县| 沭阳县| 茂名市| 晋江市| 昭平县| 衡阳市| 涿鹿县| 驻马店市| 奉化市| 郑州市| 中江县| 临颍县| 桐柏县| 柳河县| 潢川县| 新巴尔虎左旗| 津南区| 江北区|