Spring的擴展功能

Spring的擴展功能

Spring的核心就是BeanFactory,在原生的BeanFactory實現->XmlBeanFactory中,最小化的創建了一個BeanFactory,但是我們在Spring框架中使用的往往不是這個BeanFactory的實現.

ApplicationContext

Context的繼承樹

通過查看這個繼承樹我們不難看出,在Spring2.0-Reactive的實現也是繼承了ApplicationContext

起點

上面這段代碼來自SpringBoot的main函數,我們可以發現,refresh就是在這個地方調用的,Spring的整個留着也是從這裏開始加載的

	@Override
	public final void refresh() throws BeansException, IllegalStateException {
		try {
			super.refresh();
		}
		catch (RuntimeException ex) {
			stopAndReleaseReactiveWebServer();
			throw ex;
		}
	}

跟進去之後可以看到實際上是調用了AbstractApplicationContext的方法.

@Override
	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.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 這裏實現了一個空函數方便我們擴展
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				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();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

這裏就是Spring 初始化的整個流程,獲取到beanFactory之後就是開始對Spring功能的擴展,在這些擴展裏給開發者流出了很多可擴展的切面,根據這裏的,比如BeanFactoryPostProcess.


強調一下,Spring的擴展功能有很多,這裏我只記錄自己遇到的和使用過的

添加ApplicationContextAwareProcess處理器

該處理器會掃描我們的Bean如果屬於Aware會將我們需要的對象set進去.
實際上ApplicationContextAwareProcess實現了BeanPostProcess

對於實現了BeanPostProcess的方法我們只需要關心他的兩個方法:

  • postProcessBeforeInitialization
  • postProcessAfterInitialization

這裏簡單介紹下BeanPostProcess是如何實現的:

這段代碼的出處是創建Bean的時候,其內部會允許子類去實例化一個bean,所以這裏會判斷如果返回的bean不爲空則直接跳出將bean返回

直接進入AwareProcess的前置處理器

這裏可以看出如果我們的bean繼承了這幾個方法就會在這裏將實現完成

由於我們的調用在BeanFactoryProcess中已經完成了,所以需要在接下來的實例化過程中將這些類忽略掉

該擴展爲硬編碼的形式存在,所以這個擴展點主要是給我們提供一些幫助(在創建bean的時候),這些參數的獲取是通過實現傳遞的,所以需要在實例化bean的時候將他們忽略掉.

FactoryBean的使用

通過xml的方式實現過於複雜,使用FactoryBean來實現接口,通過實現FactoryBean來實現該接口定製化實例化的bean邏輯.
通過調用getObject()方法來實現Bean的實例化

BeanFactory的後處理

BeanFactory作爲Spring容器功能的基礎,存放着所有已加載的bean.我們在真正實例化bean之前可以在這裏對其進行擴展.

調用BeanFactoryPostProcess

調用BeanFactoryPostProcess是Spring通過硬編碼的形式放在初始化流程中的,通過觀察我們可以發現

下面這段代碼邏輯出自invokeBeanFactoryPostProcessors(),這裏就是調用BeanFactoryPostProcessors的地方,觀看下面這個循環判斷可以瞭解到爲什BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry會優先調用.

所有的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都放在下面的這兩個緩存中等待調用.

	List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
	List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

註冊BeanPostProcessor

註冊BeanPostProcessor的邏輯和上面的類似,對其進行一系列的校驗之後將其存儲到BeanFactory的緩存中

調用順序

這裏強調一下BeanFactoryPostProcessor和BeanDefinitionRegistry以及BeanPostProcessor的調用順序

BeanDefinitionRegistry

BeanDefinitionRegistry是最先調用的,調用的位置在上文已經給出,是初始化BeanFactoryPostProcessor的時候進行調用,而且調用的時候沒有先後順序,只是對BeanFactoryPostProcessor本身進行加工

聲明瞭幾個就調用幾次

BeanFactoryPostProcessor

BeanFactoryPostProcessor的調用位置會有以下之中:

  • 按順序調用
  • 無需調用

首先調用排序好的BeanFactoryPostProcessor,在調用沒有排序的BeanFactoryPostProcessor

聲明瞭幾個就調用幾次

BeanFactoryPostProcessor

BeanFactoryPostProcessor這個方法的調用位置根據Bean的實例化決定,在Bean的實例化前後會調用其中的兩個方法

所有的Bean在實例化的時候都會調用

初始化ApplicationEventMulticaster

ApplicationEventMulticaster的初始化過程比較簡單,這裏在默認的情況下會註冊一個Spring默認的管理器,如果用戶自己指定也可以由用戶注入.

這段代碼的源碼內容也比較簡單直觀,這裏把他的多播器列出來

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

這裏會將所有的時間廣播到所有的監聽器上,如果有異步執行器則會使用異步處理.

註冊監聽器

這裏顧名思義,就是將我們的listener註冊到監聽器上,簡而言之就是add()到緩存的List中.

初始化非延遲加載單例

在這裏會將所有的非延遲單例完成加載,這麼做是一件好事,因爲我們的bean錯誤可以及時發現.

finishRefresh

Spring的開啓和結束事件就是在這裏發出的,通過ApplicationEventMulticaster來發布Spring的各種狀態.

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