1. 程式人生 > >【Spring原始碼閱讀】 Spring容器初始化流程

【Spring原始碼閱讀】 Spring容器初始化流程

文章目錄


以下面測試程式碼為例:

public class BaseTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
        TestBean testBean = context.getBean("testBean", TestBean.class
); testBean.echo(); } }

執行後,首先呼叫ClassPathXmlApplicationContext建構函式

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
	this(new String[] {configLocation}, true, null);
}

具體呼叫以下構造方法:

// configLocations = new String[] {configLocation}
// refresh = true,表示要重新整理初始化容器
// parent = null,表示不存在父容器 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { // 通過層層呼叫父建構函式,主要初始化了this.resourcePatternResolver=new PathMatchingResourcePatternResolver(this);後續可以通過適配符尋找符合條件的java類 super(parent); // 遍歷解析傳入的配置檔案路徑,將路徑中的佔位符替換成相關的環境變數。 setConfigLocations(configLocations); if (refresh) { // true // 呼叫父類AbstractApplicationContext中定義的refresh方法,完成Spring容器和應用上下文的建立工作。 refresh(); } }

refresh方法原始碼

具體refresh程式碼如下:

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 供子類拓展,新增建立前必需屬性,校驗如果必需屬性不存在則丟擲MissingRequiredPropertiesException異常
		prepareRefresh();

		// 呼叫子類實現方法獲取(建立或重新整理)BeanFacotry容器,對於ClassPathXmlApplicationContext,主要呼叫了AbstractRefreshableApplicationContext中實現的方法
		// 在這裡,將xml配置檔案中 的Bean解析成了一個個BeanDefinition,建立一個beanName-> beanDefinition 的 map
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 設定類載入器,spel解析器,屬性編輯解析器等,忽略特定介面的依賴註冊(在特定時刻相關Bean再完成注入),註冊一些系統Bean供依賴注入使用。
		prepareBeanFactory(beanFactory);

		try {
			// BeanFactory建立完的後置處理。當前為空實現,供子類拓展
			postProcessBeanFactory(beanFactory);

			// 呼叫BeanFacotry的相關後置處理器,如果實現了Order相關介面,會先進行排序。
			invokeBeanFactoryPostProcessors(beanFactory);

			// 註冊相關BeanPostProcessor,供Bean生成前後呼叫。
			registerBeanPostProcessors(beanFactory);

			// 初始化國際化資訊源
			initMessageSource();

			// 初始化Spring相關上下文時間廣播器
			initApplicationEventMulticaster();

			// 模版方法供子類實現,用於初始化一些特殊Bean配置等
			onRefresh();

			// 註冊實現了ApplicationListener介面的事件監聽器,用於後續廣播器廣播事件
			registerListeners();

			// BeanFactory初始化完成時呼叫,初始ConversionService Bean,凍結beanFactory配置,並開始建立BeanFactory中所有非懶載入的單例Bean
			finishBeanFactoryInitialization(beanFactory);

			// 初始化Lifecycle處理器,呼叫onRefresh方法,廣播ContextRefreshedEvent。
			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;
		}
	}
}

prepareRefresh實現

下面先粗略講解refresh函式下每一步操作的原始碼實現:

// 供子類拓展,新增建立前必需屬性,校驗如果必需屬性不存在則丟擲MissingRequiredPropertiesException異常
protected void prepareRefresh() {
	this.startupDate = System.currentTimeMillis();

	synchronized (this.activeMonitor) {
		this.active = true;
	}

	if (logger.isInfoEnabled()) {
		logger.info("Refreshing " + this);
	}

	// 內部是一個空實現,主要供子類拓展自己ApplicationContext,設定必需的屬性
	initPropertySources();

	// 校驗必需的屬性是否存在,具體參考下面的程式碼
	getEnvironment().validateRequiredProperties();
}

public void validateRequiredProperties() {
	MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
	for (String key : this.requiredProperties) {
	    // 如果存在屬性缺失,記錄下來
		if (this.getProperty(key) == null) {
			ex.addMissingRequiredProperty(key);
		}
	}
	// 存在缺失屬性則丟擲異常
	if (!ex.getMissingRequiredProperties().isEmpty()) {
		throw ex;
	}
}

obtainFreshBeanFactory實現

// 呼叫子類實現方法獲取(建立或重新整理)BeanFacotry容器,對於ClassPathXmlApplicationContext,主要呼叫了AbstractRefreshableApplicationContext中實現的方法
// 在這裡,將xml配置檔案中 的Bean解析成了一個個BeanDefinition,建立一個beanName-> beanDefinition 的 map
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 重新整理初始化BeanFactory,核心在這一步
	refreshBeanFactory();
	// 獲取上一步初始化的BeanFactory
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (logger.isDebugEnabled()) {
		logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
	}
	return beanFactory;
}

refreshBeanFactory方法實現

具體實現位於AbstractRefreshableApplicationContext類下:

protected final void refreshBeanFactory() throws BeansException {
    // 如果已經存在,先銷燬存在的
	if (hasBeanFactory()) {
	    // 銷燬工廠的所有相關單例Bean
		destroyBeans();
		// 清理工廠相關配置
		closeBeanFactory();
	}
	try {
	    // 通過new DefaultListableBeanFactory(getInternalParentBeanFactory())建立一個空工廠例項
	    // 其中getInternalParentBeanFactory()=null
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		// 記錄對映id -> DefaultListableBeanFactory到一個靜態Map
		beanFactory.setSerializationId(getId());
		// 定製Bean工廠,主要供使用者自定義子類拓展是否允許BeanDefinition重寫(預設true)、迴圈引用(預設true)等功能。
		customizeBeanFactory(beanFactory);
		// 讀取xml配置,將配置中定義的Bean以BeanDefinition封裝儲存到beanFactory中。
		loadBeanDefinitions(beanFactory);
		// 記錄引用。
		synchronized (this.beanFactoryMonitor) {
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

prepareBeanFactory方法實現

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 設定類載入器,spel解析器,屬性編輯解析器等 context's class loader etc.
	beanFactory.setBeanClassLoader(getClassLoader());
	beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

	//忽略特定介面的實現類依賴注入,在Spring特定初始實現了這些相關介面的Bean的特定時刻再統一完成注入,避免重複注入等問題。具體是在ApplicationContextAwareProcessor中完成
	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型別,則注入beanFactory物件,如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext型別則注入當前物件(applicationContext物件)
	// 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);

	// 判斷是否定義了名為loadTimeWeaver的bean,如果定義了則新增loadTimeWeaver功能的beanPostProcessor擴充套件,並且建立一個臨時的classLoader來讓其處理真正的bean。spring的loadTimeWeaver主要是通過 instrumentation 的動態位元組碼增強在裝載期注入依賴
	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()));
	}

	// 註冊環境相關的Bean到容器中,後續便支援這些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方法實現

總體方法實現邏輯:呼叫所有註冊在Spring容器中的實現BeanFactoryPostProcessors介面Bean的postProcessBeanFactory方法。如果這些BeanFactoryPostProcessor實現了Order介面,會先進行排序再依次呼叫。通過這些BeanFactoryPostProcessors,可以對BeanFacotry進一步定製,如修改裡面的Bean屬性等。

// 有兩種方式新增具體的後置處理器。
// 一種是程式設計式新增:`context.addBeanFactoryPostProcessor`,這個通過getBeanFactoryPostProcessors獲取
// 另一種是通過xml配置`<bean class="com.xx.XxxBeanFactoryPostProcessor" />`,這個通過beanFactory.getBeansOfType獲取
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	Set<String> processedBeans = new HashSet<String>();
	// 如果是BeanDefinitionRegistry的實現類,需要獲取出來,呼叫其中的postProcessBeanDefinitionRegistry方法
	if (beanFactory instanceof BeanDefinitionRegistry) {
	    
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
		List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
				new LinkedList<BeanDefinitionRegistryPostProcessor>();
		for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
		    // 如果是BeanDefinitionRegistryPostProcessor的例項,還需要呼叫postProcessBeanDefinitionRegistry()方法
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryPostProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
				registryPostProcessors.add(registryPostProcessor);
			}
			else {
				regularPostProcessors.add(postProcessor);
			}
		}
		// 呼叫基於getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false)獲取的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry,注意這裡根據實現Order介面進行優先順序排序
		Map<String, BeanDefinitionRegistryPostProcessor> beanMap = beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
		List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
				new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
		OrderComparator.sort(registryPostProcessorBeans);
		for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
		// 呼叫上述方法的基於BeanFactoryPostProcessor介面的postProcessBeanFactory方法
		invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		processedBeans.addAll(beanMap.keySet());
	}
	else {
		// 僅呼叫通過程式設計註冊的處理器方法
		invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
	}

	// 根據Type=BeanFactoryPostProcessor獲取相關的後置處理器,由於BeanDefinitionRegistryPostProcessor屬於
	String[] postProcessorNames =BeanFactoryPostProcessor的子類,所以後面會過濾掉上面呼叫過的processedBeans
			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

	// 區分實現了PriorityOrdered,Ordered等介面和未實現Order介面的後置處理器,依次排序後呼叫。
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
	List<String> orderedPostProcessorNames = new ArrayList<String>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
	for (String ppName : postProcessorNames) {
		if (processedBeans.contains(ppName)) {
			// skip - already processed in first phase above
		}
		else if (isTypeMatch(ppName, PriorityOrdered.class)) {
			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
		}
		else if (isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);
		}
	}

	// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
	OrderComparator.sort(priorityOrderedPostProcessors);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	OrderComparator.sort(orderedPostProcessors);
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

	// Finally, invoke all other BeanFactoryPostProcessors.
	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
}
// 具體invokeBeanFactoryPostProcessors方法實現如下:
private void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    // 依次遍歷呼叫其中的postProcessBeanFactory
	for (BeanFactoryPostProcessor postProcessor : postProcessors) {
		postProcessor.postProcessBeanFactory(beanFactory);
	}
}
	

registerBeanPostProcessors方法實現

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 根據BeanPostProcessor型別獲取容器中具體的BeanNames
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// 區分實現了PriorityOrdered,Ordered等介面和未實現Order介面的後置處理器,依次排序後新增到ArrayList,最後呼叫時確保呼叫順序。
	// 如果是MergedBeanDefinitionPostProcessor的例項,會收集起來排序後再次重新註冊,、
	// MergedBeanDefinitionPostProcessor中定義了postProcessMergedBeanDefinition方法
	//會在建立Bean例項後,填充Bean屬性和呼叫其中所有後置處理器的postProcessBeforeInitialization前呼叫postProcessMergedBeanDefinition,
	//用來提供機會修改MergedBeanDefinition
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
	List<String> orderedPostProcessorNames = new ArrayList<String>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
	for (String ppName : postProcessorNames) {
		if (isTypeMatch(ppName, PriorityOrdered.class)) {
			BeanPostProcessor pp = beanFactory.
            
           

相關推薦

spring原始碼分析IOC容器初始(二)

前言:在【spring原始碼分析】IOC容器初始化(一)中已經分析了匯入bean階段,本篇接著分析bean解析階段。 1.解析bean程式呼叫鏈 同樣,先給出解析bean的程式呼叫鏈: 根據程式呼叫鏈,整理出在解析bean過程中主要涉及的類和相關方法。 2.解析bean原始碼分

Spring原始碼閱讀 Spring容器初始流程

文章目錄 refresh方法原始碼 prepareRefresh實現 obtainFreshBeanFactory實現 refreshBeanFactory方法實現 prepareBeanFactory方法實現 invokeBeanFa

Spring原始碼閱讀BeanDefinition原理與載入流程

BeanDefinition介面定義及其相關子類實現 在Spring容器初始化過程中,Spring會將配置檔案中配置的Java類封裝成一個個BeanDefinition。 BeanDefinition儲存了具體代表Bean的類,並通過實現了AttributeAccessor介面定義了

Spring原始碼閱讀Spring原始碼閱讀環境搭建

閱讀Spring原始碼,我們可以通過以下兩種方式: 直接在Idea/Eclipse上建立自己的java maven/gradle專案,匯入Spring特定版本依賴Jar和原始碼,直接執行測試程式碼,逐步除錯閱讀 從github直接獲取Spring原始碼專案,基於Spri

Spring Framework 深入—— IoC容器初始 -> Bean定義資源的Resource定位

基本概念 ApplicationContext 繼承體系 本文主要關注ApplicationContext的繼承體系,至於BeanFactory的分支,以後再研究。 BeanFactory or ApplicationContext? Bea

Spring原始碼閱讀IOC核心容器基礎和繼承體系結構

BeanFactory BeanFacotry作為Spring的根容器物件,提供了對Bean的基礎操作功能,包括例項化、配置、管理Bean等。 ApplicationContext ApplicationContext對BeanFactory進行了進一步地封裝,內建了Bean

Spring原始碼閱讀 DefaultListableBeanFactory繼承結構講解分析

在基於ClassPathXmlApplicationContext建立BeanFactory時,我們從程式碼裡看到,建立的BeanFactory的型別是DefaultListableBeanFactory。 下面我們來分析下DefaultListableBeanFactory的繼承結構,

Spring原始碼閱讀populateBean實現 依賴注入原始碼解析

在完成Bean例項化後,Spring容器會給這個Bean注入相關的依賴Bean,在原始碼中,這一步通過類AbstractAutowireCapableBeanFactory中的populateBean方法完成。 測試程式碼 下面開始進入原始碼分析之前,先基於以下例項進行: /

Spring原始碼閱讀 preInstantiateSingletons方法分析,單例Bean獲取/例項流程

在初始化ClassPathXmlApplicatonContext過程中,核心初始化邏輯在AbstractApplicationContext的refresh函式中: public void refresh() throws BeansException, IllegalStateE

Spring- IOC容器初始過程

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

Spring IOC原始碼詳解之容器初始

可以進入parseBeanDefinitionElement方法中,裡面詳細講了Bean元素是如何解析的。 //解析<Bean>元素的入口 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {

java原始碼閱讀Map介面

/* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to l

GAN ZOO閱讀模式正則的生成對抗網路 MODE REGULARIZED GENERATIVE ADVERSARIAL NETWORKS

原文地址: https://arxiv.org/abs/1612.02136 引用之請註明出處。 Tong Che 1,Yanran Li 2 3,Athul Paul Jacob 1,Yoshua Bengio 1,Wenjie Li 2 1 蒙特利爾學習演算法

JDK原始碼分析01-物件序列ObjectOutputStream

上一篇文章提到反序列化列舉類仍是單例,而普通類物件不是單例,下面我們先分析一下序列化過程,序列化就是呼叫ObjectOutStream的物件的writeObject方法。我們先看一下序列化涉及的比較重要的一個ObjectStreamClass,JDK中的描述是:類的序列化描述

SpringBoot框架——從SpringBoot看IoC容器初始流程之方法分析

目錄 一、概觀Spring Boot 二、Spring Boot應用初始化 2.1 初始化入口 2.2 SpringApplication的run方法 2.3 方法分析 三、容器建立與初始化 3.1 creatApplicationContext()方法 3.2 prepareContext(co

Spring MVCDispatcherServlet詳解(容器初始超詳細過程原始碼分析)

DispatcherServlet類相關的結構圖DispatcherServlet的初始化程式DispatcherServlet初始化了什麼,可以在其initStrategies()方法中知曉,這個方法如下: protected void initStrategies(App

Spring原始碼解析—— 結合SpringMVC過程理解IOC容器初始之註解部分探究

前面的文章寫了xml中直接配置bean進行IOC的過程解析,接下來會針對註解進行IOC容器初始化的過程解析 因為會與之前的內容存在部分重疊,因此會針對相同的部分簡略帶過,針對不同的部分做重點說明:   一、Xml的配置和程式碼中的註解配置: applicationContext.xml配置新

Spring原始碼解析(一)Idea搭建Spring原始碼閱讀環境

準備階段 Idea Gradle Git jdk 詳細步驟 以上工具安裝好,這裡主要記錄一下Git和Gradle,工作一直都是用的svn和Maven,所以對於Git和Gradle瞭解的不算多。 (1) Gradle安裝        Gradle的安裝很簡單,和

Spring原始碼分析1-Tomcat的初始

org.apache.catalina.startup.ContextConfig.configureStart() org.apache.catalina.startup.ContextConfig.webConfig() 進入org.apache.catali

spring原始碼學習之路---IOC容器初始要義之bean定義載入(四)

上章說到要帶各位去看看bean定義載入的要義,其實就是loadBeanDefinitions這個方法的具體實現步驟,下面我們跟隨這個方法去看下它到底是如何載入bean定義的。 上面是我擷取的實現了loadBeanDefinitions的類級別截圖,loadBeanDefinit