Spring源碼解析之BeanFactoryPostProcessor(三)

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

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定義註冊後置處理器)。java

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

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

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

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

在下面的代碼<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實現類執行。ide

此外,這裏咱們也注意到參數beanFactoryPostProcessors是由AbstractApplicationContext調用getBeanFactoryPostProcessors()方法傳入的,getBeanFactoryPostProcessors()會返回beanFactoryPostProcessors這個列表,beanFactoryPostProcessors默認爲一個空列表,咱們能夠調用addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)將本身建立的bean工廠後置處理器對象添加到beanFactoryPostProcessors這個列表。所以,在執行invokeBeanFactoryPostProcessors(...)最初會先執行由程序員建立的BeanDefinitionRegistryPostProcessor對象。spring-boot

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~2九、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();
	}
	……
}
相關文章
相關標籤/搜索