Java 圖解Spring啟動時的後置處理器工作流程是怎樣的

探究Spring的後置處理器

本次我們主要探究invokeBeanFactoryPostProcessors();後面的代碼下次再做解析;

入口代碼refresh()

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// ......
applicationContext.refresh();
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 啟動前的準備工作:記錄啟動時間,活動標記為啟動以及環境屬性變量集合的初始化
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// Prepare the bean factory for use in this context.
			//還是一些準備工作,添加瞭兩個後置處理器:ApplicationContextAwareProcessor,ApplicationListenerDetector
			//還設置瞭 忽略自動裝配 和 允許自動裝配 的接口
			//對環境,系統環境,系統屬性三個Bean如果不存在某個bean的時候,spring就自動生成singleton bean(Not bd)
			//還設置瞭bean表達式解析器 等
			prepareBeanFactory(beanFactory);
			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 空方法
				postProcessBeanFactory(beanFactory);
				// Invoke factory processors registered as beans in the context.
				//執行自定義的BeanFactoryProcessor和內置的BeanFactoryProcessor
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				// Initialize message source for this context.
				initMessageSource();
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses.
				onRefresh();
				// Check for listener beans and register them.
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);
				// Last step: publish corresponding event.
				finishRefresh();
			}
			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

流程圖

在這裡插入圖片描述

prepareRefresh剖析

該方法主要做啟動前的準備工作:記錄啟動時間,活動標記為啟動以及環境屬性變量集合的初始化;

	protected void prepareRefresh() {
		// Switch to active.
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);
		// Initialize any placeholder property sources in the context environment.
		// 空方法
		initPropertySources();
		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();
		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}
		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

obtainFreshBeanFactory刨析

主要是獲取context上下文中的bean工廠;

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// CAS保證同步
		refreshBeanFactory();
		// 返回beanFactory- DefaultListableBeanFactory.class
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		return beanFactory;
	}

prepareBeanFactory刨析

做一些準備工作,添加瞭兩個後置處理器ApplicationContextAwareProcessorApplicationListenerDetector;

設置瞭bean表達式解析器等;

通過工廠的接口可以設置瞭忽略自動裝配,和允許自動裝配;

對環境、系統環境、系統屬性三個Bean如果不存在某個bean的時候,spring就自動生成singletonBean(Not bd);

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)  {
    	// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		//設置bean表達式解析器
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		//屬性編輯器支持
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		//添加一個後置處理器:ApplicationContextAwareProcessor,此後置處理處理器實現瞭BeanPostProcessor接口
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		//以下接口,忽略自動裝配
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   		// .....
    	// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		//以下接口,允許自動裝配,第一個參數是自動裝配的類型,,第二個字段是自動裝配的值
		// 這個接口僅會將註入的參數XXX.class註入為指定的值,但不影響XXX.class創建Bean對象;
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    	// Register default environment beans.
		// 環境,系統環境,系統屬性 因此通常情況下,這三個Bean是沒有bd的
		//如果沒有註冊過bean名稱為XXX,spring就自己創建一個名稱為XXX的singleton bean
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
}

invokeBeanFactoryPostProcessors剖析

執行自定義的BeanFactoryProcessor和內置的BeanFactoryProcessor;

getBeanFactoryPostProcessors()方法是我們手動通過執行addBeanFactoryPostProcessor(XX)設置自定義的後置處理器。如果初始化執行到這,沒有手動增加後置處理器的話,那麼此時List<BeanFactoryPostProcessor>的size()為empty;

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	// getBeanFactoryPostProcessors是spring允許我們手動添加BeanFactoryPostProcessor
	// 即:annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX);
    // 未手動添加的話,getBeanFactoryPostProcessors()為empty
		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()方法,從而去掃描並執行BeanFactoryProcessorBeanDefinitionRegistryPostProcessor;

我們通過繼承關系看,BeanDefinitionRegistryPostProcessor實際上是繼承BeanFactoryProcessor接口的;

在這裡插入圖片描述

  • BeanDefinitionRegistryPostProcessor:主要掃描類解析類;
  • BeanFactoryProcessor:主要給配置類進行增強代理;

這裡面需要看我們的BeanFactory的類型;初始時BeanFactory的類型是DefaultListableBeanFactory;因此,該bean工廠是實現BeanDefinitionRegistry;

在這裡插入圖片描述

該方法的具體流程如下(按初始化進入到這裡描述):

  • 循環遍歷手動添加的後置處理器(並不排序);
  • 若該bfp是bdrp則直接執行bdrp. postProcessBeanDefinitionRegistry();
  • 取出內置的bdrp,分為實現瞭PriorityOrdered,Ordered和都沒有實現的三類;

初始這裡隻有一個,就是我們在初始化reader()時,註冊瞭一個ConfigurationClassPostProcessor.class;

在這裡插入圖片描述

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
		PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {}

將上面三類直接執行bdrp. postProcessBeanDefinitionRegistry();

然後將手動加入和內置的bdrp執行bfp.postProcessBeanFactory();

上面的已經執行完瞭:

  1. 手動添加的後置處理器的bdrf. postProcessBeanDefinitionRegistry()bfp.postProcessBeanFactory();
  2. 內置的bdrp. postProcessBeanDefinitionRegistry()

取出內置的bfp,分為實現瞭PriorityOrdered, Ordered和都沒有實現的三類;

目前這裡內置的有兩個。但其中config上面已經執行過瞭,此處隻執行下方的一個;

在這裡插入圖片描述

將上面三類直接執行bfp. postProcessBeanDefinitionRegistry();

清除緩存中的bd,因為後處理器可能有修改瞭原始元數據,例如替換值中的占位符;

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

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

		// 如果不是BeanDefinitionRegistry 則直接執行beanFactoryPostProcessors
		// 剛啟動時傳入的beanFactory是DefaultListableBeanFactory,他是實現瞭BeanDefinitionRegistry 因此會走這裡
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			// bf後置處理器集合(手動添加與bdr後置處理器集合【下面的那個集合】):因為bdrp屬於bfp
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			// bdr後置處理器集合(手動添加與spring自己的)
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			// 循環傳進來的beanFactoryPostProcessors,剛啟動時未手動增加的情況下beanFactoryPostProcessors肯定沒有數據
			// 因為beanFactoryPostProcessors是獲得手動添加的,而不是spring掃描的
			// 隻有手動調用annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX)才會有數據
			// 執行手動添加的beanFactoryPostProcessors, 如果是BeanDefinitionRegistryPostProcessor,則執行其postProcessBeanDefinitionRegistry再加到list中
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
			//一個臨時變量,用來裝載BeanDefinitionRegistryPostProcessor為瞭排序
			//BeanDefinitionRegistry繼承瞭PostProcessorBeanFactoryPostProcessor
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// 獲得實現BeanDefinitionRegistryPostProcessor接口的類
			// 就是ConfigurationClassPostProcessor(Spring自己添加的-在reader()時增加的)
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//獲得ConfigurationClassPostProcessor類,並且放到currentRegistryProcessors
					//ConfigurationClassPostProcessor是很重要的一個類,它實現瞭BeanDefinitionRegistryPostProcessor接口
					//BeanDefinitionRegistryPostProcessor接口又實現瞭BeanFactoryPostProcessor接口
					//ConfigurationClassPostProcessor是極其重要的類
					//裡面執行瞭掃描Bean,Import,ImportResouce等各種操作
					//用來處理配置類(有兩種情況 一種是傳統意義上的配置類,一種是普通的bean)的各種邏輯
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//把name放到processedBeans,後續會根據這個集合來判斷處理器是否已經被執行過瞭
					processedBeans.add(ppName);
				}
			}
			//處理排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//合並Processors,為什麼要合並,因為registryProcessors是裝載BeanDefinitionRegistryPostProcessor的
			//一開始的時候,spring隻會執行BeanDefinitionRegistryPostProcessor獨有的方法
			//而不會執行BeanDefinitionRegistryPostProcessor父類的方法,即BeanFactoryProcessor的方法
			//所以這裡需要把處理器放入一個集合中,後續統一執行父類的方法
			registryProcessors.addAll(currentRegistryProcessors);
			//可以理解為執行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
			//Spring熱插播的體現,像ConfigurationClassPostProcessor就相當於一個組件,Spring很多事情就是交給組件去管理
			//將spring提供的RegistryProcessors(就是這個ConfigurationClassPostProcessor)執行其postProcessBeanDefinitionRegistry
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//清空臨時變量
			currentRegistryProcessors.clear();
			// 再次根據BeanDefinitionRegistryPostProcessor獲得BeanName,看這個BeanName是否已經被執行過瞭,有沒有實現Ordered接口
			// 如果沒有被執行過,也實現瞭Ordered接口的話,把對象推送到currentRegistryProcessors,名稱推送到processedBeans
			// 如果沒有實現Ordered接口的話,這裡不把數據加到currentRegistryProcessors,processedBeans中,後續再做處理
			// 這裡才可以獲得我們定義的實現瞭BeanDefinitionRegistryPostProcessor的Bean
			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);
			//合並Processors
			registryProcessors.addAll(currentRegistryProcessors);
			//執行有Ordered的BeanDefinitionRegistryPostProcessor
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//清空臨時變量
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			// 下面的代碼就是執行沒有實現PriorityOrdered接口也沒有Ordered的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();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			//registryProcessors集合裝載BeanDefinitionRegistryPostProcessor
			//上面的代碼是執行bfr後置處理器子類獨有的方法,這裡需要再把bfr後置處理器父類的方法也執行一次
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			//regularPostProcessors裝載BeanFactoryPostProcessor,執行BeanFactoryPostProcessor的方法
			//但是regularPostProcessors一般情況下,是不會有數據的,隻有在外面手動添加BeanFactoryPostProcessor,才會有數據
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			// 若bfp沒有繼承bdrp則直接執行手動增加bf後置處理器的後置處理器
			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!
		// 找到BeanFactoryPostProcessor實現類的BeanName數組
		// 處理Spring自己的bf後置處理器
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		// PriorityOrdered的bf後置處理器集合
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		// Ordered的bf後置處理器集合
		List<String> orderedPostProcessorNames = new ArrayList<>();
		// 無PriorityOrdered無Ordered的bf後置處理器集合
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		//循環BeanName數組
		for (String ppName : postProcessorNames) {
			//如果這個Bean被執行過瞭,跳過
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			//如果實現瞭PriorityOrdered接口,加入到priorityOrderedPostProcessors
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			//如果實現瞭Ordered接口,加入到orderedPostProcessorNames
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			//如果既沒有實現PriorityOrdered,也沒有實現Ordered。加入到nonOrderedPostProcessorNames
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		//排序處理priorityOrderedPostProcessors,即實現瞭PriorityOrdered接口的BeanFactoryPostProcessor
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//執行priorityOrderedPostProcessors
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		//執行實現瞭Ordered接口的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		// 執行既沒有實現PriorityOrdered接口,也沒有實現Ordered接口的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		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...
		// 清除瞭allBeanNamesByType&singletonBeanNamesByType()
		// 清除緩存中的bd,因為後處理器可能有修改瞭原始元數據,例如替換值中的占位符
		beanFactory.clearMetadataCache();
	}

到此這篇關於Java 圖解Spring啟動時的後置處理器工作流程是怎樣的的文章就介紹到這瞭,更多相關Java Spring 後置處理器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: