第四節 spring容器的擴展功能

前言

經過前面幾章的分析,我們已經已經對Spring中的容器功能有了簡單的瞭解,在前面的章 節中我們完整的瞭解了spring解析xml裝載BeanDefination以及註冊IOc容器初始化一個完整Bean的過程。然而這只是spring的冰山一角,對於java開發人員來說 ApplicationContext已經爛熟於耳了,今天我們圍繞它講一講容器的擴展功能。話不多說直接擼碼!

早在第二節中已經介紹了spring加載XMl的幾種方式,本次我們以 ClassPathXmlApplicationContext作爲切入點:

ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("/application.xml");

核心過程

1.ClassPathXmlApplicationContext

public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

在這個方法中設置路徑是必不可少的步驟,ClassPathXmlApplicationContext中可以將配置文件路徑以數 組的方式傳入,對數組進行解析並進行加載。而對於解析及功能實現都在refresh()中實現;還得往下看,這也是spring一貫的作風。

2.refresh()函數

進入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.告訴子類刷新內部bean工廠,初始化beanfactory,並加載xml文件讀取。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// Prepare the bean factory for use in this context.準備在這種情況下使用的bean工廠 對BeanFactory進行各種功能填充
			prepareBeanFactory(beanFactory);
			try {
				// Allows post-processing of the bean factory in context subclasses.允許在上下文子類中對bean工廠進行後處理。
				postProcessBeanFactory(beanFactory);
				// Invoke factory processors registered as beans in the context.調用在上下文中註冊爲bean的工廠處理器。
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation.注註冊攔截Bean創建的Bean處理器,這裏只是註冊,真正的調用是在getBean時候
				registerBeanPostProcessors(beanFactory);
				// Initialize message source for this context.爲上下文初始化Message源,即不同語言的消息體,國際化處理
				initMessageSource();
				// Initialize event multicaster for this context.爲此上下文初始化事件多播器。
				initApplicationEventMulticaster();
				// initialize other special beans in specific context subclasses.在特定上下文子類中初始化其他特殊bean。
				onRefresh();
				// Check for listener beans and register them.檢查偵聽器bean並註冊它們
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.實例化所有剩餘的(非延遲初始化)單例。
				finishBeanFactoryInitialization(beanFactory);
				// Last step: publish corresponding event.最後一步:完成刷新過程,通知生命週期處理器lifecycleProcessor刷新過程,同時發佈相應的事件。
				finishRefresh();
			} catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("...");
				}
				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			} finally {
				resetCommonCaches();
			}
		}
	}

首先總結一下這個函數的作用:

  1. 初始化前的準備工作,例如對系統屬性或者環境變量進行準備及驗證。
    在某種情況下項目的使用需要讀取某些系統變量,而這個變量的設置很可能會影響着系統 的正確性,那麼ClassPathXmlApplicationContext爲我們提供的這個準備函數就顯得非常必要, 它可以在Spring啓動的時候提前對必需的變量進行存在性驗證。
  2. 初始化BeanFactory,並進行XML文件讀取。
    之前有提到ClassPathXmlApplicationContext包含着BeanFactory所提供的_切特徵,那麼 在這一步驟中將會複用BeanFactory中的配置文件讀取解析及其他功能,這一步之後,
    ClassPathXmlApplicationcontext實際上就已經包含了 BeanFactory所提供的功能,也就是可以 進行bean的提取等基礎操作了。
  3. 對BeanFactory進行各種功能填充。
    ©Qualifier與@Autowired應該是大家非常熟悉的註解,那麼這兩個註解正是在這一步驟中 增加的支持。
  4. 子類覆蓋方法做額外的處理。
    Spring之所以強大,爲世人所推崇,除了它功能上爲大家提供了便例外,還有一方面是它 的完美架構,開放式的架構讓使用它的程序員很容易根據業務需要擴展已經存在的功能。這種 開放式的設計在Spring中隨處可見,例如在本例中就提供了一個空的函數實現postProcess- BeanFactory來方便程序員在業務上做進一步擴展。
  5. 激活各種BeanFactory處理器。
  6. 註冊攔截bean創建的bean處理器,這裏只是註冊,真正的調用是在getBean時候。
  7. 爲上下文初始化Message源,即對不同語言的消息體進行國際化處理。
  8. 初始化應用消息廣播器,並放入“applicationEventMulticaster" bean中。
  9. 留給子類來初始化其他的bean。
  10. 在所有註冊的bean中査找listener bean,註冊到消息廣播器中。
  11. 1初始化剩下的單實例(非惰性的。
  12. 完成刷新過程,通知生命週期處理器liffecycleProcessor刷新過程,同時發出Context- RefreshEvent通知事件。

1:)prepareRefresh-環境準備

protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();
		// 設置容器的狀態
		this.closed.set(false);
		this.active.set(true);
		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}
		// Initialize any placeholder property sources in the context environment 空的 //留給子類覆蓋
		initPropertySources();
		// 驗證需要的屬性文件是否都已經放入環境中
		getEnvironment().validateRequiredProperties();
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
  1. initPropertySources函數是個空實現,這也正符合Spring的開放式結構設計,給用戶最大擴展Spring的能力。 用戶可以根據自身的需要重寫initPropertySources方法,並在方法中進行個性化的屬性處理及 設置。
  2. validateRequiredProperties則是對屬性進行驗證。

2:)obtainFreshBeanFactory-初始化beanfactory,並加載xml文件讀取

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 初始化BeanFactory,並進行XML文件讀取,並將得到的BeanFacotry記錄在當前實體的屬性中
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

obtainFreshBeanFactory 方法從字面理解是獲取 BeanFactoryo。我們都知道,Application- Context是對BeanFactory的功能上的擴展,不但包含了 BeanFactory的全部功能更在其基礎上 添加了大量的擴展應用,那麼obtainFreshBeanFactory函數正是實現BeanFactory的地方,也就是經 過了這個函數後Applicationcontext就已經擁有了 BeanFactory的全部功能。我們還發現核心代碼的實現又委託給了 refreshBeanFactory函數;

protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// 創建 BeanFactory  XmlBeanFactory就是DefaultListableBeanFactory的子類,提供了 XmlBeanDefinitionReader 類型的 reader 屬性,也就是說 DefaultListableBean-Factory是容器的基礎。必須首先要實例化
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 爲了序列化指定id,如果需要的話,讓這個BeanFactory從id反序列化到BeanFactory對象
			beanFactory.setSerializationId(getId());
			// 定製beanFactory,設置相關屬性,包括是否允許覆蓋同名稱的不同定義的對象以及循環依賴
			customizeBeanFactory(beanFactory);
			// 加載 BeanDefinitiono
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("...);
		}
	}

這個函數是非常重要的,在此重點講一下:

  1. 創建 DefaultListableBeanFactory0
    不知道大家是否還有映像在第二節開篇的時候,BeanFactory bf = new XmlBeanFactory(“application.xm”),這一句代碼;其中的 XmlBeanFactory 繼承自 DefaultListableBeanFactory ,並提供了 XmlBeanDefinitionReader 類型的 reader 屬性,也就是說 DefaultListableBean-Factory是容器的基礎。必須首先要實例化,那麼在這裏就是實例化DefaultListableBeanFactory 的步驟。
  2. 指定序列化ID。
  3. 定製 BeanFactory。
  4. 加載 BeanDefinition,沒錯這一步正是我們整個第二節所講的類容。
  5. 使用全局變量記錄BeanFactory類實例。
    因爲DefkultListableBeanFactory類型的變量beanFactory是函數內的局部變量,所以要使用 全局變量記錄解析結果。

3:)prepareBeanFactory-容器功能擴展

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		// /設置 beanFactory 的 classLoader 爲當前 context 的 classLoader
		beanFactory.setBeanClassLoader(getClassLoader());
		// 設置beanFactory的表達式語言處理器,Spring3增加了表達式語言的支持,默認可以使用# {bean, xxx}的形式來調用相關屬性值。
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		// 爲beanFactory增加了一個默認的propertyEditor,這個主要是對bean的屬性等設置管理的一個工具
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		// BeanPostProcessor
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		// 設置了幾個忽略自動裝配的接口
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		// 設置了幾個自動裝配的特殊規則
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		// 增加對AspectJ的支持
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		// 添加默認的系統環境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());
		}
	}

流式的處理流程爲容器擴展功能屬性,這也是spring如此強大的原因,正是由這些組件的支持。

  • 增加對SpEL語言的支持,比如#{xxx.xxx}這樣的表達式。
  • 增加對屬性編輯器的支持。
  • 增加對一些內置類,比如EnvironmentAware、MessageSourceAware的信息注入。
  • 設置了依賴功能可忽略的接口。
  • 註冊一些固定依賴的屬性。
  • 增加Aspect!的支持。
    將相關環境變量及屬性註冊以單例模式註冊。

在此我們重點講一下 ApplicationContextAwareProcessor處理器,在上述代碼中有這樣一句

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));其實主要目的就是註冊個BneaPostProcessor。ApplicationContextAwareProcessor 實現 BeanPostProcessor 接口,在第三節的內容中,在bean實例化的時候,也就是Spring激活bean的init-method的前後,會調用BeanPostProcessor 的 postProcessBefbrelnitialization 方法和 postProcessAfterlnitialization 方法。同樣,對 於ApplicationContextAwareProcessor我們也關心這兩個方法。我們發現 postProcessBefbrelnitialization方法中又調用了 invokeAwareInterfeces;我們或許已經或多或少了解了 Spring的用意,實現這些Aware接口的bean在被初始 化之後,可以取得一些對應的資源。

4:)invokeBeanFactoryPostProcessors-激活bean的工廠處理器

上述類容以及第三節的部分我們已經說了BeanPostProcessor 接口;在此我們先了解下BeanFactoryPostProcessor的用法。BeanFactoryPostProcessor 接口跟 BeanPostProcessor 類似,可以對 bean 的定義(配置元數 據)進行處理。也就是說,Spring IoC容器允許BeanFactoryPostProcessor在容器實際實例化任 何其他的bean之前讀取配置元數據,並有可能修改它。如果你願意,你可以配置多個 BeanFactoryPostProcessor0你還能通過設置“order”屬性來控制 BeanFactoryPostProcessor 的執行次序。簡言之就是BeanFactoryPostProcessor接口能在容器實例化bean之前讓你修改bean的一些屬性。

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();
		// 對 BeanDefinitionRegistry 類型的處理
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
			// 硬編碼註冊的後處理器
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					// BeanDefinitionRegistryPostProcessor	在 BeanFactoryPostProcessor 的基礎上還有自己定義的方法,需要先調用
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					//記錄常規 BeanFactoryPostProcessor
					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)) {
					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)) {
					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) {
				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);
			// 常規的BeanFactoryPostProcessors
			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!
		// 對於配置中讀取的BeanFactoryPostProcessor的處理
		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<>();
		for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		// 按照 order進行排序
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
		// Finally, invoke all other BeanFactoryPostProcessors.
		// 無序的直接調用
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
	nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
		beanFactory.clearMetadataCache();
	}

從上面的方法中我們看到,對於BeanFactoryPostProcessor的處理主要分兩種情況進行,一個 是對於BeanDefinitionRegistry類的特殊處理,另一種是對普通的BeanFactoryPostProcessor進行處 理。而對於每種情況都需要考慮硬編碼注入註冊的後處理器以及通過配置注入的後處理器。
對於BeanDefinitionRegistry類型的處理類的處理主要包括以下內容。

  1. 對於硬編碼註冊的後處理器的處理,主要是通過AbstractApplicationContext中的添加處 理器方法 addBeanFactoryPostProcessor 進行添加。

    public void addBeanFactoryPostProcessor(
        BeanFactoryPostProcessor beanFactoryPostProcessor) {
        this ・ beanFactoryPostProcessors.add(beanFactoryPostProcessor);
    }
    

    添加後的後處理器會存放在beanFactoiyPostProcessors中,而在處理

    BeanFactoryPostProcessor 時候會首先檢測 beanFactoryPostProcessors 是否有數據。當然,BeanDefinitionRegistryPostProcessor 繼承自BeanFactoryPostProcessor,不但有BeanFactoryPostProcessor的特性,同時還有自己定義 的個性化方法,也需要在此調用。所以,這裏需要從beanFactoryPostProcessors中挑出 BeanDefinitionRegistryPostProcessor 的後處理器,並進行其 postProcessBeanDefinitionRegistry 方 法的激活。

    添加後的後處理器會存放在beanFactoiyPostProcessors中,而在處理BeanFactoryPostProcessor 時候會首先檢測 beanFactoryPostProcessors 是否有數據。當然,BeanDefinitionRegistryPostProcessor 繼承自BeanFactoryPostProcessor,不但有BeanFactoryPostProcessor的特性,同時還有自己定義 的個性化方法,也需要在此調用。所以,這裏需要從beanFactoryPostProcessors中挑出 BeanDefinitionRegistryPostProcessor 的後處理器,並進行其 postProcessBeanDefinitionRegistry 方 法的激活。

  2. 記錄後處理器主要使用了 3個List完成。

    • registryPostProcessors:記錄通過硬編碼方式註冊的 BeanDefinitionRegistryPostProcessor 類型的處理器。
    • regularPostProcessors:記錄通過硬編碼方式註冊的BeanFactoryPostProcessor類型的處 理器。
    • registryPostProcessorBeans:記錄通過配置方式註冊的 BeanDefinitionRegistryPostProcessor 類型的處理器。
  3. 對以上所記錄的List中的後處理器進行統一調用BeanFactoryPostProcessor的 postProcessBeanFactory 方法。

  4. 對 beanFactoryPostProcessors 中非 BeanDefinitionRegistryPostProcessor 類型的後處理器進行 統一的 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法調用。

  5. 普通 beanFactory 處理。
    BeanDefinitionRegistryPostProcessor 只對 BeanDefinitionRegistry 類型的 ConfigurableListable- BeanFactory有效,所以如果判斷所示的beanFactory並不是BeanDefinitionRegistry,那麼便可 以忽略 BeanDefinitionRegistryPostProcessor,而直接處理 BeanFactoryPostProcessor,當然獲取 的方式與上面的獲取類似。這裏需要提到的是,對於硬編碼方式手動添加的後處理器是不需要做任何排序的,但是在 配置文件中讀取的處理器,Sping並不保證讀取的順序。所以,爲了保證用戶的調用順序的要求,Spring對於後處理器的調用支持按照PriorityOrdered或者Ordered的順序調用。

5:)registerBeanPostProcessors-註冊eanPostProcessor處理器

首先強調一點這裏只是註冊並不是調用,具體是在getBean()的時候調用,這一點我們在第三節也說到了;下面我們繼續看代碼:

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		/*
		* BeanPostProcessorChecker•是一個普通的信息打印,可能會有些情況,
		•當Spring的配置中的後處理器還沒有被註冊就已經開始了 bean的初始化時
		*便會打印出BeanPostProcessorChecker中設定的信息
		*/
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		// 使用PriorityOrdered保證順序
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		// 存儲 MergedBeanDefinitionPostProcessor
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		// 使用Ordered保證順序
		List<String> orderedPostProcessorNames = new ArrayList<>();
		// 無序的
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			} else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}
		// First, register the BeanPostProcessors that implement PriorityOrdered.首先,註冊實現PriorityOrdered的BeanPostProcessor
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered. 接下來,註冊實現Ordered的BeanPostProcessor。
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors. 現在,註冊所有常規BeanPostProcessor。
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
		// Finally, re-register all internal BeanPostProcessors. 最後,重新註冊所有內部BeanPostProcessor。
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);
		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		// 添加 ApplicationListener 探測器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

乍一看BeanPostProcessor的處理與BeanFactoryPostProcessor的處理極爲 相似,但是似乎又有些不一樣的地方。對於BeanFactoryPostProcessor 的處理,不但要實現註冊功能,而且還要實現對後處理器的激活操作,所以需要載入配置中的定義並激活;而對於BeanPostProcessor並不需要馬上調用,再說,硬編碼的方式實現的功能是將後處理器提取並調用,這裏並不需要調用,當然不需要考慮硬編碼的方式了,這裏的 功能只需要將配置文件的BeanPostProcessor提取出來並註冊進入beanFactory就可以了。

6:)initMessageSource-爲上下文初始化Message源

不做過多說明,根據字眼我們就能發現他是初始化不同語言的消息體,即國際化處理相關的擴展。

7:)initApplicationEventMulticaster-初始化時間廣播

沒錯通過關鍵字我們就能知道這個方法是容器擴展監聽事件的實現。

protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		} else {
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
						"': using default [" + this.applicationEventMulticaster + "]");
			}
		}
	}

通過代碼我們發現,該方法就是兩種情況:

  • 如果用戶自定義了事件廣播器,那麼使用用戶自定義的事件廣播器。
  • 如果用戶沒有自定義事件廣播器,那麼使用默認的ApplicationEventMulticaster().

在默認的廣播事件處理器 SimpleApplicationEventMulticaster 中我們發現了一段很有價值的代碼:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			} else {
				invokeListener(listener, event);
			}
		}
	}

很明顯了,當產生Spring事件的時候會默認使用SimpleApplicationEventMulticaster的 multicastEvent來廣播事件,遍歷所有監聽器,並使用監聽器中的onApplicationEvent方法來進 行監聽器的處理。而對於每個監聽器來說其實都可以獲取到產生的事件,但是是否進行處理則 由事件監聽器來決定。

8:)registerListeners-註冊監聽器

protected void registerListeners() {
		// Register statically specified listeners first. 首先註冊靜態指定的偵聽器
		for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
		}
		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let post-processors apply to them!
		// 配置文件註冊的監聽器處理
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}
		// Publish early application events now that we finally have a multicaster...
		// 獲取所有的事件 統一處理
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

spring的監聽、事件處理是很好用也很使用的功能,上述代碼很好理解獲取所有的監聽器以及所有的事件,統一交給第七步中所配置的處理器處理。

9:)finishBeanFactoryInitialization-初始化所有非延遲加載的bean

我們都知道spring的bean有懶加載(@lazy)與立即加載的區別,在此就是初始化非延遲加載的bean:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.爲此上下文初始化轉換服務
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}
		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}
		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.停止使用臨時的ClassLoader進行類型匹配。
		beanFactory.setTempClassLoader(null);
		// Allow for caching all bean definition metadata, not expecting further changes.允許緩存所有bean定義元數據,而不期望進一步的更改。
		beanFactory.freezeConfiguration();
		// Instantiate all remaining (non-lazy-init) singletons. 初始化非延遲的單利的bean
		/**
		 * Applicationcontext實現的默認行爲就是在啓動時將所有單例bean提前進行實例化。提 前實例化意味着作爲初始化過程的一部分,
		 * Applicationcontext實例會創建並配置所有的單例 bean通常情況下這是一件好事,因爲這樣在配置中的任何錯誤就會即刻被發現
		 */
		beanFactory.preInstantiateSingletons();
	}

在此我們重點關注一下 beanFactory.preInstantiateSingletons()這個函數,進入這個這個函數:

public void preInstantiateSingletons() throws BeansException {
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Pre-instantiating singletons in " + this);
		}
		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		// 獲取之前註冊的 beanDefinition對象
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			// 裝配 RootBeanDefinition
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				// 判斷是否是 factoryBean
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						} else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				} else {
					// 初始化 bean 也就是將 beanDefinition -》 完整bean的過程
					getBean(beanName);
				}
			}
		}
		// Trigger post-initialization callback for all applicable beans...觸發所有適用bean的初始化後回調...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				} else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

是不是有一種很親切的感覺?特別是 getBean(beanName)函數?到這裏再次與之前的第三節內容對應起來了,又到了初始化bean的環節,在此不做闡述。

9:)finishRefresh-刷新容器

至此整個容器的擴展功能已經完畢了,在此更新容器狀態,發佈最終的容器啓動完成事件。

後語

不積跬步,無以至千里 ,不積小流 ,無以成江海。擼起袖子加油幹!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章