Spring初始化容器源碼分析

我的博客

在這裏插入圖片描述

碼雲地址帶有上篇文章中所用的中文註釋和測試類,分支my-test

Spring GitHub地址
碼雲地址

Spring 是漸進式的工具,並不具有很強的侵入性,它的模塊也劃分得很合理,即使你的應用不是 web 應用,或者之前完全沒有使用到 Spring,而你就想用 Spring 的依賴注入這個功能,其實完全是可以的,它的引入不會對其他的組件產生衝突

ApplicationContext繼承結構

構建 ApplicationContext的方案有很多,先來看看大體的繼承結構是怎麼樣的:

在這裏插入圖片描述

我們可以使用 FileSystemXmlApplicationContextClassPathXmlApplicationContextAnnotationConfigApplicationContext 這三個類來構建 ApplicationContext

1、FileSystemXmlApplicationContext 的構造函數需要一個 xml 配置文件在系統中的路徑,和 ClassPathXmlApplicationContext 基本上一樣。

2、ClassPathXmlApplicationContext 是根據 xml 文件內容來構建 ApplicationContext,就是在 ClassPath 中尋找 xml 配置文件。

3、AnnotationConfigApplicationContext 是基於註解來使用的,它不需要配置文件,採用 java 配置類和各種註解來配置,目前主流方式。

BeanFactory繼承結構

ApplicationContext 其實就是一個 BeanFactory,生產 bean 的工廠,它負責生產和管理各個 bean 實例,繼承結構:

在這裏插入圖片描述

  1. ApplicationContext 繼承了 ListableBeanFactory,這個 Listable 的意思就是,通過這個接口,我們可以獲取多個 Bean,大家看源碼會發現,最頂層 BeanFactory 接口的方法都是獲取單個 Bean 的。

  2. ApplicationContext 繼承了 HierarchicalBeanFactory,Hierarchical 單詞本身已經能說明問題了,也就是說我們可以在應用中起多個 BeanFactory,然後可以將各個 BeanFactory 設置爲父子關係。

  3. AutowireCapableBeanFactory 用來自動裝配 Bean 用的,但是仔細看上圖,ApplicationContext 並沒有繼承它,不過不用擔心,不使用繼承,不代表不可以使用組合,如果你看到 ApplicationContext 接口定義中的最後一個方法 getAutowireCapableBeanFactory() 就知道了。

  4. ConfigurableListableBeanFactory 也是一個特殊的接口,看圖,特殊之處在於它繼承了第二層所有的三個接口,而 ApplicationContext 沒有。這點之後會用到。

BeanFactory、ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory、ApplicationContext 這幾個接口中的方法:

BeanFactory
ApplicationContext
ListableBeanFactory
AutowireCapableBeanFactory

啓動過程分析

public class Test {

    public static void main(String[] args) {
        // 實例化ApplicationContext容器對象
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        context.getBean(Z.class);
    }

}

通過創建AnnotationConfigApplicationContext對象,執行構造方法裏的refresh()方法(初始化容器),爲什麼是 refresh(),而不是 init() 這種名字的方法。因爲 ApplicationContext 建立起來以後,其實我們是可以通過調用 refresh() 這個方法重建的,refresh() 會將原來的 ApplicationContext 銷燬,然後再重新執行一次初始化操作

在這裏插入圖片描述

refresh() 方法裏面調用的方法很多,一個一個方法來看大概做了些什麼事情,首先是prepareRefresh()

在這裏插入圖片描述

prepareRefresh

這個方法主要是記錄啓動時間,校驗 xml 配置文件,檢驗environment的properties是否正確,initPropertySources會調用GenericWebApplicationContext的實現,設置容器的環境,初始化容器的屬性

在這裏插入圖片描述

obtainFreshBeanFactory

因爲上面調用了GenericApplicationContext的實現,觸發構造方法,這裏將會創建 BeanFactory,也就是創建了DefaultListableBeanFactory,如下:

	/**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

obtainFreshBeanFactory方法其實就是拿到之前創建的 beanFactory 對象,spring容器是通過 ConfigurableListableBeanFactory 這個bean工廠進行真正的bean加載。其主要做了三個動作,刷新 beanFactory,獲取 beanFactory,返回 beanFactory

	/**
	 * Tell the subclass to refresh the internal bean factory
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 刷新 BeanFactory並指定序列化id
        // 調用了AtomicBoolean的compareAndSet方法,保證只刷新一次
        // 如果再次調用refresh()方法,則會拋出異常
		refreshBeanFactory();
		// 返回剛剛創建的 BeanFactory
		return getBeanFactory();
	}

這步完成後,配置文件就會解析成一個個 Bean 定義,註冊到 BeanFactory 中,註冊也只是將這些信息都保存到了註冊中心(說到底核心是一個 beanName-> beanDefinition 的 map),這裏說的 Bean 還沒有初始化,只是配置信息都提取出來了

在這裏插入圖片描述

prepareBeanFactory

在註冊bean之前先給beanFactory配置一些屬性,它們可以幫助beanFactory後期去解析、註冊其他的bean

在這裏插入圖片描述

如果上述幾個Aware不使用ignoreDependencyInterface會有什麼問題呢?如果我們寫一個實現類,然後給他默認配置ApplicationContext屬性,而這個ApplicationContext是我們自己new的,這就導致了我們使用的不是spring自己生成的ApplicationContext,所以spring爲了避免我們手誤自己註冊下這個屬性,而幫我們忽略。

registerResolvableDependency就是當我們使用自動注入比如@AutoWired注入BeanFactory 類型時,他會幫我們注入目前輸入的實例對象,而不會去注入他的其他實現類,這是爲了避免我們使用其他的自定義的實例對象

在這裏插入圖片描述

postProcessBeanFactory

Spring中並沒有具體去實現postProcessBeanFactory方法,是提供給想要實現BeanPostProcessor的三方框架使用的。誰要使用誰就去實現。其實就是向上下文中添加了一系列的Bean的後置處理器,後置處理器工作的時機是在所有的beanDefinition加載完成之後,bean實例化之前執行。簡單來說Bean的後置處理器是用來修改BeanDefinition的屬性信息的

在這裏插入圖片描述

invokeBeanFactoryPostProcessors

實例化和調用所有 BeanFactoryPostProcessor(包括其子類 BeanDefinitionRegistryPostProcessor),在該方法中完成IoC容器的初始化;代碼較多,推薦閱讀此篇文章

此方法執行完成後,我們自己創建加了註解的Bean會被put到beanDefinitionMap中,上篇文章中有講

在這裏插入圖片描述

registerBeanPostProcessors

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		// 獲取所有實現BeanPostProcessor接口的bean的名稱
		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.
		// 加一是因爲方法末尾會註冊一個ApplicationListenerDetector接口的實現類
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		// 註冊 BeanPostProcessorChecker,用於每個bean的初始化完成後,做一些簡單的檢查
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		// 緩存實現了priorityOrdered接口的bean
		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.
		// 排序、註冊
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		// 緩存實現Ordered接口的bean
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		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.
		// 緩存沒有實現兩個接口的bean
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		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.
		// 排序註冊所有的實現了MergedBeanDefinitionPostProcessor接口的bean
		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).
		// 註冊ApplicationListenerDetector,用來檢查所有的ApplicationListener
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

這裏只是註冊,相當於整理所有的BeanPostProcessor,把其提出來,按執行循序放到list中,供後續調用。原來我們只知道所有的BeanPostProcessor都在IoC容器中以bean的形式存在着,但是我們不知道應該如何去執行,以什麼順序去執行。經過該方法解決了該問題

在這裏插入圖片描述

最後幾個方法

        // Initialize message source for this context.
        // 初始化當前 ApplicationContext 的 MessageSource,主要做國際化處理
        initMessageSource();

        // Initialize event multicaster for this context.
        // 初始化當前 ApplicationContext 的事件廣播器
        initApplicationEventMulticaster();

        // Initialize other special beans in specific context subclasses.
        // 具體的子類可以在這裏初始化一些特殊的 Bean(在初始化 singleton beans 之前)
        // 空殼方法,類似postProcessBeanFactory()
        onRefresh();

        // Check for listener beans and register them.
        // 註冊事件監聽器,監聽器需要實現 ApplicationListener 接口
        registerListeners();

        // Instantiate all remaining (non-lazy-init) singletons.
        // 初始化所有的 singleton beans,上篇文章已分析
        //(lazy-init 的除外)
        finishBeanFactoryInitialization(beanFactory);

        // Last step: publish corresponding event.
        // 最後,廣播事件,ApplicationContext 初始化完成
        finishRefresh();

        // Destroy already created singletons to avoid dangling resources.
        // 銷燬已經初始化的 singleton 的 Beans,以免有些 bean 會一直佔用資源
        destroyBeans();

        // Reset 'active' flag.
        // 設置active表示爲false
        cancelRefresh(ex);

        // Reset common introspection caches in Spring's core, since we
        // might not ever need metadata for singleton beans anymore...
        // 清除反射的緩存
        // 清除註解的相關緩存
        // 清除classloader緩存
        resetCommonCaches();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章