Spring源碼解析之BeanFactoryPostProcessor(三)


在上一章中筆者介紹了refresh()的<1>處是如何獲取beanFactory對象,下面我們要來學習refresh()方法的<2>處是如何調用invokeBeanFactoryPostProcessors方法執行bean工廠后置處理器,這個方法在筆者看來是整個refresh()方法最重要的方法之一,因為就是在這個方法完成了掃描類路徑下所有的類,並將類解析成BeanDefinition注冊到spring容器中。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	……
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			……
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//<1>
			……
			try {
				……
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);//<2>
				……
			}

			catch (BeansException ex) {
				……
			}

			finally {
				……
			}
		}
	}
	……
}

  

在了解invokeBeanFactoryPostProcessors(beanFactory)方法的運作原理前,我們需要對spring的兩個接口有一個基本的認識:BeanFactoryPostProcessor(bean工廠后置處理器)、BeanDefinitionRegistryPostProcessor(bean定義注冊后置處理器)。

public interface BeanFactoryPostProcessor {
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

  

如果有看過筆者先前寫的Spring源碼解析之BeanFactoryPostProcessor(一)應該對BeanFactoryPostProcessor有印象,在這一章節中筆者說過BeanFactoryPostProcessor接口實現類的執行時機是在掃描完所有BeanDefinition並注冊到spring容器之后,以及實例化bean之前。這一章筆者也創建了一個BeanFactoryPostProcessor接口的實現類Test1BeanFactoryPostProcessor,在postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法中筆者將userService的beanDefinition的class替換成OrderService.class,當我們從spring容器獲取userService對應的bean,bean的類型為OrderService而不是UserService。

那么筆者不禁有個疑問,spring又是如何根據程序員指定的類路徑將路徑下的類解析成BeanDefinition並注冊進spring容器呢?答案就在BeanDefinitionRegistryPostProcessor。根據spring官方文檔介紹:BeanDefinitionRegistryPostProcessor接口的作用就是向spring容器注冊BeanDefinition,且BeanDefinitionRegistryPostProcessor的執行時機在BeanFactoryPostProcessor之前,而BeanFactoryPostProcessor的作用更傾向於在spring容器獲取到所有BeanDefinition后,在實例化bean之前,修改BeanDefinition的屬性。比如設定連接池的最大連接數不能超過1000,我們就可以在BeanFactoryPostProcessor獲取連接池BeanDefinition的最大連接數,如果超過一千則將最大連接數改為1000。又或者我們提供了一個聊天服務接口ChatService,並實現了一個與之同名的實現類,假設這個實現類是基於MySQL實現的一個聊天服務,后續我們又開發了一個基於Redis的聊天服務實現類ChatService2,當外部需要依賴注入ChatService接口時我們更希望注入的是基於Redis實現的ChatService2聊天服務而不是原先基於MySQL實現的ChatService,也可以實現一個BeanFactoryPostProcessor,並將chatService的BeanDefinition的class替換成ChatService2。

Spring源碼解析之BeanFactoryPostProcessor(一)講述AnnotatedBeanDefinitionReader的時候,筆者曾說過這個類的構造方法會執行到AnnotationConfigUtils.registerAnnotationConfigProcessors(...),在這個方法內會注冊一些基礎組件的BeanDefinition注冊進spring容器中。當時筆者說過其中一個基礎組件:ConfigurationClassPostProcessor就是完成BeanDefinition掃描的工作,而ConfigurationClassPostProcessor這個類就實現了BeanDefinitionRegistryPostProcessor,在postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法中掃描出配置類指定路徑下所有的類,並篩選出那些可以成為BeanDefinition的類注冊到spring容器中。

此外,BeanDefinitionRegistryPostProcessor的父類是BeanFactoryPostProcessor,從某個角度上來看:BeanDefinitionRegistryPostProcessor接口的實現也可以看作是BeanFactoryPostProcessor。因此refresh()方法中調用的invokeBeanFactoryPostProcessors(beanFactory),除了執行BeanFactoryPostProcessor的實現類,還會執行BeanDefinitionRegistryPostProcessor的實現類,而且BeanDefinitionRegistryPostProcessor實現類的執行時機會先於BeanFactoryPostProcessor的實現類。

當調用invokeBeanFactoryPostProcessors(beanFactory)方法時,會進而執行到PostProcessorRegistrationDelegate類的靜態方法invokeBeanFactoryPostProcessors(...),這個方法接收一個beanFactory和BeanFactoryPostProcessor列表。

在下面的代碼<1>處,會先判斷傳入的beanFactory對象能否轉型成BeanDefinitionRegistry,在Spring源碼解析之BeanFactoryPostProcessor(二)章節中筆者曾介紹這針對注解(AnnotationConfigApplicationContext)和XML(ClassPathXmlApplicationContext)應用上下文spring各開發了兩個父類GenericApplicationContext和AbstractRefreshableApplicationContext來獲取beanFactory,這兩個父類的beanFactory對象類型為DefaultListableBeanFactory,DefaultListableBeanFactory類既是ConfigurableListableBeanFactory接口的實現類,也是BeanDefinitionRegistry接口的實現類,所以大部分情況下會進入<1>處的分支。因為通常我們啟動spring容器不是通過注解就是通過XML初始化應用上下文,而注解和XML應用上下文返回的beanFactory類型實際上都是DefaultListableBeanFactory,除非是重寫refreshBeanFactory()、獲取getBeanFactory()這兩個方法,那么可以自定義一個BeanFactory的實現類且不實現ConfigurableListableBeanFactory接口,也就不會進到分支<1>。

在進入到<1>處的分支后會循環beanFactoryPostProcessors列表,如果列表內的元素可以轉型成BeanDefinitionRegistryPostProcessor,則執行元素實現的的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法,將元素添加到registryProcessors列表,如果不能轉型則添加到regularPostProcessors列表,到達一定時機,spring會執行registryProcessors和regularPostProcessors兩個列表中元素實現的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)。這里也印證了spring官方文檔所說的BeanDefinitionRegistryPostProcessor實現類會優先於BeanFactoryPostProcessor實現類執行。

此外,這里我們也注意到參數beanFactoryPostProcessors是由AbstractApplicationContext調用getBeanFactoryPostProcessors()方法傳入的,getBeanFactoryPostProcessors()會返回beanFactoryPostProcessors這個列表,beanFactoryPostProcessors默認為一個空列表,我們可以調用addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)將自己創建的bean工廠后置處理器對象添加到beanFactoryPostProcessors這個列表。因此,在執行invokeBeanFactoryPostProcessors(...)最初會先執行由程序員創建的BeanDefinitionRegistryPostProcessor對象。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	……
	private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
	……
	@Override
	public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
		Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
		this.beanFactoryPostProcessors.add(postProcessor);
	}
	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}
	……
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
		……
	}
	……
}

final class PostProcessorRegistrationDelegate {
	……
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();
		
		if (beanFactory instanceof BeanDefinitionRegistry) {//<1>
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
			……
		}
		
		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}
		……
	}
	……
}

  

這里我們創建一個bean工廠后置處理器(BeanFactoryPostProcessor)和BeanDefinition注冊后置處理器(BeanDefinitionRegistryPostProcessor)的實現類,並創建者兩個類的實例添加到上下文對象然后看看兩個實現類實現的接口的回調時機。

Test3BeanDefinitionRegistryPostProcessor.java

package org.example.beanFactoryPostProcessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class Test2BeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("test2 postProcessBeanFactory...");
    }
}

 

Test3BeanDefinitionRegistryPostProcessor.java 

package org.example.beanFactoryPostProcessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

public class Test3BeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("test3 postProcessBeanDefinitionRegistry...");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("test3 postProcessBeanFactory...");
    }
}

  

測試用例:

    @Test
    public void test05() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
        ac.addBeanFactoryPostProcessor(new Test2BeanFactoryPostProcessor());
        ac.addBeanFactoryPostProcessor(new Test3BeanDefinitionRegistryPostProcessor());
        ac.refresh();
    }

  

打印結果:

test3 postProcessBeanDefinitionRegistry...
test3 postProcessBeanFactory...
test2 postProcessBeanFactory...

  

可以看到spring會優先執行BeanDefinitionRegistryPostProcessor實現類的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法,再執行BeanDefinitionRegistryPostProcessor實現類的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法,最后才執行BeanFactoryPostProcessor實現類的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法。

需要注意一點的是:spring有兩種提供bean工廠后置處理器(BeanFactoryPostProcessor )的方式:

  1. 創建一個bean工廠后置處理器對象並調用addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)將對象添加到spring容器中供spring回調。
  2. 編寫一個BeanFactoryPostProcessor的實現類,並且給類標記上@Component注解,spring會獲取實現了BeanFactoryPostProcessor接口的類,並生成bean調用其接口,比如前面筆者所編寫的Test1BeanFactoryPostProcessor。

這兩種方式不同點是:前者是程序員手動創建bean工廠后置處理器對象再交由spring執行,但這個對象本身不是一個bean,這個對象雖然實現了spring的接口,但它的生命周期不歸spring管理;后者是bean工廠后置處理器對象的創建由spring負責,這個對象在spring容器中是一個bean,spring同樣會這個bean的回調方法,這個bean的生命周期由spring管理。

上面這兩種提供方式同樣適用於BeanDefinition注冊后置處理器(BeanDefinitionRegistryPostProcessor),因為BeanDefinitionRegistryPostProcessor本身就可以看成是一個BeanDefinitionRegistryPostProcessor。

標記了@Component注解的BeanFactoryPostProcessor實現類,它的bean對象不在AbstractApplicationContext類的beanFactoryPostProcessors列表中。換句話說beanFactoryPostProcessors列表的元素必須手動創建對象並添加,假設我們開發了兩個BeanDefinitionRegistryPostProcessor的實現類:FooBeanDefinitionRegistryPostProcessor和BarBeanDefinitionRegistryPostProcessor,FooBeanDefinitionRegistryPostProcessor是用過手動創建對象添加到beanFactoryPostProcessors列表,BarBeanDefinitionRegistryPostProcessor是通過@Component注解由spring創建bean對象。下面代碼<1>處遍歷beanFactoryPostProcessors列表中只有一個FooBeanDefinitionRegistryPostProcessor對象會得到執行,而BarBeanDefinitionRegistryPostProcessor對應的bean會在后面的代碼進行接口回調,但不會在<1>處進行回調。

final class PostProcessorRegistrationDelegate {
	……
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();
		
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {//<1>
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
			……
		}
		……
	}
	……
}

  

我們來對比下下面18~29、32~42這兩段代碼,這兩段代碼完成的工作是極其相似的,會遍歷所有已經注冊到spring容器的BeanDefinition,找出BeanDefinitionRegistryPostProcessor實現類對應的beanName並將其返回。之后會在<1>、<2>處判斷這個beanName對應的class在實現了BeanDefinitionRegistryPostProcessor接口的前提下,是否分別實現了PriorityOrdered、Ordered接口。

Ordered是PriorityOrdered的父接口,PriorityOrdered本身並沒有實現任何方法,而是直接繼承Ordered,實現了PriorityOrdered的類會優先於實現了Ordered的類執行。Ordered接口會要求實現類返回一個數值用於排序,返回數值越小的實現類排在越前。之后這兩段代碼都會從bean工廠根據beanName和類型獲取BeanDefinitionRegistryPostProcessor實現類的bean對象,並將待執行的bean對象加到currentRegistryProcessors列表,將對應的beanName加入到processedBeans表示已經處理這個bean,再對currentRegistryProcessors列表進行排序,這里就會用到Ordered接口要求返回的數值,越小排越前,即返回數值越小越優先執行。

排序完畢后會將currentRegistryProcessors列表的元素加入到registryProcessors列表,然后調用invokeBeanDefinitionRegistryPostProcessors(...)方法遍歷currentRegistryProcessors列表每個對象,執行其實現的postProcessBeanDefinitionRegistry(...)方法,開始真正處理列表中每一個bean對象,處理完畢后再清空currentRegistryProcessors列表。而registryProcessors列表在未來的某個時機,會執行列表中所有對象實現的postProcessBeanFactory(...)方法。

需要注意一點:第一段代碼會找出所有實現了BeanDefinitionRegistryPostProcessor和PriorityOrdered接口的實現類,將其beanName加入到processedBeans表示這個bean已經處理,即便這個時候尚未執行bean對象的postProcessBeanDefinitionRegistry(...)方法,但后續會執行。第二段代碼在找出BeanDefinitionRegistryPostProcessor和Ordered接口實現類的同事,也會找到第一段代碼已經找到的實現類,因為PriorityOrdered是Ordered的子接口,意味着實現了PriorityOrdered同樣實現了Ordered,但這里不會出現重復執行同一個bean對象的的postProcessBeanDefinitionRegistry(...)方法,因為在第二段代碼會再判斷beanName是否在processedBeans中,只有不在processedBeans集合的beanName才允許執行,如果beanName已經在processedBeans,表明這個bean在之前已經執行了postProcessBeanDefinitionRegistry(...)方法。currentRegistryProcessors列表在這兩段代碼都只會存放尚未執行的BeanDefinitionRegistryPostProcessor實現類,並且在這兩段代碼執行完畢后都會清空currentRegistryProcessors列表,所以我們也不用擔心registryProcessors列表會存在相同的bean對象。

這里還可以和大家先劇透一下,先前我們介紹的在構造AnnotatedBeanDefinitionReader對象時會將一些基礎組件以BeanDefinition的形式注冊到spring容器中待后續spring容器根據BeanDefinition構造bean,其中一個基礎組件ConfigurationClassPostProcessor就會在下面第一段代碼(即18~29行)執行,ConfigurationClassPostProcessor為BeanDefinitionRegistryPostProcessor和PriorityOrdered兩個接口的實現類,在執行這個實現類的postProcessBeanDefinitionRegistry(...)方法時,就會掃描配置類指定的類路徑,並篩選類路徑下可以成為BeanDefinition的類注冊進spring容器,供后續spring根據BeanDefinition構造bean。ConfigurationClassPostProcessor是如何完成BeanDefinition的篩選和注冊后續筆者還會講解,這里我們只要知道第一段代碼會完成類路徑的掃描即可。

final class PostProcessorRegistrationDelegate {
	……
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
			
		// Invoke BeanDefinitionRegistryPostProcessors first, if any.	
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			……
			// 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.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {//<1>
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
			
			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {//<2>
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
			……
		}
		……
	}
	……
}

  

BeanDefinitionRegistryPostProcessor接口是spring較為底層的接口,spring-context包下也只有ConfigurationClassPostProcessor實現了BeanDefinitionRegistryPostProcessor接口,除了ConfigurationClassPostProcessor類之外spring家族再無BeanDefinitionRegistryPostProcessor接口的實現。此外就筆者目前所見的開源框架,除了spring-context、spring-boot外,也只有mybatis集成spring的包(mybatis-spring)實現了BeanDefinitionRegistryPostProcessor接口,即:org.mybatis.spring.mapper.MapperScannerConfigurer,不過MapperScannerConfigurer類並沒有實現PriorityOrdered和Ordered的接口,所以MapperScannerConfigurer並不會再上面的代碼執行,而是會在后續的某個時機執行。

在先后執行完實現了PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor實現類,會用一個while循環不斷從bean工廠獲取尚未執行的BeanDefinitionRegistryPostProcessor實現類,因為可能存在spring在執行一個BeanDefinitionRegistryPostProcessor實現類的postProcessBeanDefinitionRegistry(...)方法時有新的BeanDefinitionRegistryPostProcessor類以BeanDefinition的形式注冊進bean工廠。每次循環都會把尚未執行的BeanDefinitionRegistryPostProcessor實現類加入到registryProcessors列表,直到獲取不到尚未執行的BeanDefinitionRegistryPostProcessor實現類才會退出循環,而我們之前所說的MapperScannerConfigurer類也就是在下面的while循環執行的,退出while循環后統一執行registryProcessors和regularPostProcessors列表中對象實現的postProcessBeanFactory(...)。

已經找到整個項目中所有的BeanDefinitionRegistryPostProcessor對象,這個列表的順序會優先存儲程序員手動創建的BeanDefinitionRegistryPostProcessor對象,再存儲實現了PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor對象,,不管是內置的亦或是集成別的項目或是程序員自己開發的BeanDefinitionRegistryPostProcessor實現類,都會存到,和regularPostProcessors兩個列表中對象實現的postProcessBeanFactory(...)方法。

final class PostProcessorRegistrationDelegate {
	……
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
			
		// Invoke BeanDefinitionRegistryPostProcessors first, if any.	
		Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) { …… // 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) { 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(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } …… } …… }

  

如果beanFactory可以轉型成BeanDefinitionRegistry,則會進入分支<1>,而在分支<1>內部會做的工作我們也已經了解。如果beanFactory不能轉型成BeanDefinitionRegistry,則會進入分支<2>,這里就會執行我們手動創建的BeanFactoryPostProcessor對象的postProcessBeanFactory(...)方法。但就筆者目前的開發經驗,大部分情況下都會進入分支<1>,會進入分支<2>的情況筆者至今還未見過,希望有這方面業務經驗的同學可以不吝賜教。

在執行分支<1>或分支<2>的代碼后,會獲取spring容器內所有BeanFactoryPostProcessor實現類對應的beanName,這里依舊可能把之前已經處理過的beanName獲取出來。在遍歷這些beanName的時候如果判斷已經在processedBeans集合中,則表示已經處理過,這里就會跳過這個beanName,如果是不在processedBeans集合,則會根據是否實現PriorityOrdered、Ordered接口和都沒實現分為三組,會分別對實現了PriorityOrdered和Ordered接口的bean工廠處理器進行排序,再分組執行,最后執行沒有實現PriorityOrdered和Ordered接口的bean工廠后置處理器。

final class PostProcessorRegistrationDelegate {
	……
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
			
		// Invoke BeanDefinitionRegistryPostProcessors first, if any.	
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {//<1>
			……
		}
		
		else {//<2>
			// Invoke factory processors registered with the context instance.
			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!
		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.
		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();
	}
	……
}

  

下面我們來看看PriorityOrdered和Ordered兩個接口,正如筆者所言, PriorityOrdered接口本身並沒有要求實現任何方法,PriorityOrdered接口的設計只是為了和Ordered做一個區分,子接口會優先執行,父接口會在子接口執行完畢后才執行。這兩個接口都會要求實現類在getOrder()方法返回一個數值,數值越小排序越前。

public interface PriorityOrdered extends Ordered {
}

public interface Ordered {

	int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;

	int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

	int getOrder();

}

  

最后,我們總結下PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(...)整個方法的流程就結束本章的講解。這個方法接收一個beanFactory對象,和beanFactoryPostProcessors列表。通常情況下:beanFactoryPostProcessors列表是程序員手動創建的BeanFactoryPostProcessor對象,beanFactory可以轉型成BeanDefinitionRegistry,所以會進入下面代碼<1>處的分支。在分支<1>內部會創建兩個列表regularPostProcessors和registryProcessors,這里會遍歷beanFactoryPostProcessors列表,判斷列表中每個對象是否能轉型成BeanDefinitionRegistryPostProcessor接口,如果轉型成功則執行其實現的postProcessBeanDefinitionRegistry(...)方法並將對象存放到registryProcessors列表,轉型失敗則存放在regularPostProcessors列表。

之后在代碼的33~44行會獲取已經以BeanDefinition形式存放到spring容器內BeanDefinitionRegistryPostProcessor實現類對應的beanName,並判斷beanName對應的BeanDefinitionRegistryPostProcessor實現類是否也實現了PriorityOrdered,實現了PriorityOrdered接口則會進入<2>處的分支,從bean工廠根據beanName獲取對應的bean對象並加入到currentRegistryProcessors列表,之后會將currentRegistryProcessors列表進行排序,將列表中的元素添加到registryProcessors,執行currentRegistryProcessors列表所有對象實現的postProcessBeanDefinitionRegistry(...)方法,再清空currentRegistryProcessors列表。而在33~44行也會執行BeanDefinitionRegistryPostProcessor的實現類ConfigurationClassPostProcessor,在這個實現類的postProcessBeanDefinitionRegistry(...)方法中完成類路徑的掃描,解析類路徑下可以成為BeanDefinition的類並將其注冊到spring容器中。

代碼47~57行和33~44太過相似,不同的是后者執行的是同樣實現了Ordered接口的BeanDefinitionRegistryPostProcessor實現類,由於PriorityOrdered是Ordered的子接口,這里會把33~44行已經執行過的beanName找出來,但這些已經執行過的beanName已經存放在processedBeans集合,所以這里會過濾掉,只會執行尚未執行的Ordered和BeanDefinitionRegistryPostProcessor的實現類。

在代碼<4>處會有一個while循環,不斷去遍歷spring容器內現有BeanDefinitionRegistryPostProcessor實現類對應的beanName,這里同樣會把之前已經找到的beanName獲取出來,同樣會用processedBeans集合過濾已經處理過的beanName,只會執行尚未執行的BeanDefinitionRegistryPostProcessor實現類的bean對象。等到確定spring容器內不再有尚未執行的BeanDefinitionRegistryPostProcessor實現類就會退出while循環。此時registryProcessors已經擁有了程序員手動創建的BeanDefinitionRegistryPostProcessor對象和整個spring容器所有的BeanDefinitionRegistryPostProcessor實現類的bean對象,在<5>處會執行這些BeanDefinitionRegistryPostProcessor對象的postProcessBeanFactory(...)方法,再執行程序員手動創建的BeanFactoryPostProcessor對象的postProcessBeanFactory(...)方法,至此完成分支<1>的所有工作,所有的BeanDefinitionRegistryPostProcessor對象都先后完成了postProcessBeanDefinitionRegistry(...)和postProcessBeanFactory(...)方法的調用。

之后會獲取spring容器內所有BeanFactoryPostProcessor實現類對應的beanName,這里會遍歷這些beanName,如果已經存在processedBeans集合的beanName代表已經處理過,這里會跳過已經處理過的beanName,收集實現了PriorityOrdered或Ordered接口,和這兩個接口都沒實現的BeanFactoryPostProcessor實現類的bean對象,這里會優先對實現了PriorityOrdered接口的BeanFactoryPostProcessor對象進行排序並執行postProcessBeanFactory(...)方法,再對實現了Ordered接口的BeanFactoryPostProcessor對象進行排序再執行postProcessBeanFactory(...)方法,最后是執行沒有實現PriorityOrdered或Ordered接口的BeanFactoryPostProcessor對象的postProcessBeanFactory(...)方法。

這里也再次證實了spring對BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor兩個接口的定義:BeanDefinitionRegistryPostProcessor的實現會優先於BeanFactoryPostProcessor執行,而BeanDefinitionRegistryPostProcessor實現的postProcessBeanDefinitionRegistry(...)也會優先本身實現的postProcessBeanFactory(...)執行,最后才執行僅實現了BeanFactoryPostProcessor接口的postProcessBeanFactory(...)方法。

final class PostProcessorRegistrationDelegate {
	……
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {//<1>
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					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.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {//<2>
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {//<3>
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {//<4>
				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();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//<5>
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			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!
		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.
		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();
	}
	……
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM