天天看點

spring ioc容器源碼解讀

Spring是每個java程式員都必須要掌握的技能,很多人都想通過閱讀源碼來提升自己的技術深度,這裡分享一下我讀源碼的方法。

我覺得看源碼應該先大概的讀,知道主脈絡,然後再去讀細節,這樣才不會亂,先放上我畫的圖(不怎麼會畫,大概看看就好,最大的正方形就是ioc容器)

spring ioc容器源碼解讀

然後我們來看一下照着圖來走一下代碼

在springboot啟動類打斷點
public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
           

經過SpringApplication構造函數完成一些初始化操作後來到

SringApplication這個類的ConfigurableApplicationContext 方法,

這個方法我們主要看 this.refreshContext(context); 這一行,這是建立ioc容器的方法,其他的可以等熟悉了主要脈絡再去細看

public ConfigurableApplicationContext run(String... args) {
		//計時器執行個體,并設定計時器id,name和開始時間
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		//系統屬性設定 一般是在程式開始激活headless模式,告訴程式,現在你要工作在Headless mode下,就不要指望硬體幫忙了,你得自力更生,依靠系統的計算能力模拟出這些特性來
		configureHeadlessProperty();
		//初始化監聽器   META-INF/spring.factories檔案中擷取SpringApplicationRunListener接口的實作類。
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//啟動已經準備好的監聽器  getSpringFactoriesInstances
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			//裝配環境參數  儲存args參數
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			// 準備環境變量, 讀取 bootstrapContext application.properties檔案中的環境變量
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			// 系統配置忽略标志spring.beaninfo.ignore
			configureIgnoreBeanInfo(environment);
			//列印banner圖案
			Banner printedBanner = printBanner(environment);
			//建立ConfigurableApplicationContext(應用配置上下文)
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			//将listeners、environment、applicationArguments、banner等重要元件與上下文對象關聯
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			//這個方法很重要 ioc容器的建立
			refreshContext(context);
			//ioc容器建立後
			afterRefresh(context, applicationArguments);
			//計時結束
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
           

一路進去AbstractApplicationContext這個實作類的refresh()方法

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            //初始化工作,記錄下容器的啟動時間、标記“已啟動”狀态、處理配置檔案中的占位符
            this.prepareRefresh();
            //這個是建立bean工廠的方法主要是createBeanFactory():建立BeanFactory和loadBeanDefinitions() :加載BeanDefinination兩個方法
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //填充beanFactory屬性
            this.prepareBeanFactory(beanFactory);

            try {
            //這是一個擴充點
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
              //執行個體化并調用所有注冊的BeanFactoryPostProcessors
              this.invokeBeanFactoryPostProcessors(beanFactory);
              // 注冊 BeanPostProcessor 的實作類,注意看和 BeanFactoryPostProcessor 的差別
         // 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 兩個方法分别在 Bean 初始化之前和初始化之後得到執行。注意,到這裡 Bean 還沒初始化
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                //國際化相關
                this.initMessageSource();
                // 初始化目前 ApplicationContext 的事件廣播器
                this.initApplicationEventMulticaster();
                // 從方法名就可以知道,典型的模闆方法(鈎子方法),
         // 具體的子類可以在這裡初始化一些特殊的 Bean(在初始化 singleton beans 之前)
                this.onRefresh();
                // 注冊事件監聽器,監聽器需要實作 ApplicationListener 接口
                this.registerListeners();
                // 重點,重點,重點
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         this.finishBeanFactoryInitialization(beanFactory);
         // 最後,廣播事件,ApplicationContext 初始化完成
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }
				// 銷毀已經初始化的 singleton 的 Beans,以免有些 bean 會一直占用資源
                this.destroyBeans();
                // Reset 'active' flag.
                this.cancelRefresh(var10);
                throw var10;
            } finally {
                this.resetCommonCaches();
                contextRefresh.end();
            }

        }
    }
           

對于上面大家不知道BeanFactoryPostProcessor和BeanPostProcessor是幹嘛的。大家可以看看這篇文章

https://blog.csdn.net/caihaijiang/article/details/35552859

然後這裡給大家說一下具體每個方法做了什麼
  1. prepareRefresh
protected void prepareRefresh() {
		// Switch to active.
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		// ①在上下文環境中初始化任何占位符屬性源。
		initPropertySources();

		// ②驗證所有标記為required的屬性都是可解析的:
		// 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<>();
	}

           

ApplicationContext重新整理前的準備工作,比如設定啟動時間(startupDate),激活标志(active & closed),以及執行屬性源的初始化(見闡釋)

闡釋:

①initPropertySources()是模闆抽象方法,使用者可以根據需要進行重寫。 Warn見WebApplicationContext解析

protected void initPropertySources() {
		// For subclasses: do nothing by default.
	}
  
           

我們可以覆寫該方法,進行自定義的屬性處理以及設定。比如如果項目的啟動必須依賴于目前機器的環境變量ENV,那麼我們可以這樣寫:

protected void initPropertySources() {
		// For subclasses: do nothing by default.
		getEnvironment().setRequiredProperties("ENV")
	}
           

②getEnvironment().validateRequiredProperties(),對所有被标記為required的屬性進行驗證

在前面我們知道,這裡的envirmonent是一個StandardEnvironment,它是ConfigurablePropertyResolver的子類,故而它可以執行validateRequiredProperties()方法(因為該方法是由ConfigurablePropertyResolver接口聲明的)。

我們還知道AbstractEnvironment中聲明了一個類型為ConfigurablePropertyResolver的propertyResolver屬性,并寫死其值為PropertySourcesPropertyResolver對象。在這裡的驗證required屬性的工作也是交給了這個PropertyResolver來處理!!

具體的驗證邏輯讀者可以自行閱讀源碼,其實:

  • setRequiredProperties()是将字元串加入到一個由AbstractPropertyResolver維護的一個名為requiredProperties的Set集合中
  • validateRequiredProperties()僅僅是循環requiredProperties并驗證存在罷了。
private final ConfigurablePropertyResolver propertyResolver =
			new PropertySourcesPropertyResolver(this.propertySources);
	@Override
	public void validateRequiredProperties() throws MissingRequiredPropertiesException {
		this.propertyResolver.validateRequiredProperties();
	}
           
  1. obtainFreshBeanFactory
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}
	protected final void refreshBeanFactory() throws BeansException {
	    //如果目前存在beanFactory,則先銷毀掉
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(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);
		}
	}
}
           

概述:refreshBeanFactory()方法對ApplicationContext上下文的底層beanFactory執行真正的重新整理,先關閉之前的beanFactory(如果有的話),并為目前的ApplicationContext上下文生命周期的下一階段初始化一個新的beanFactory。

refreshBeanFactory()方法中的核心方法調用分别是:

  • createBeanFactory():建立BeanFactory
  • loadBeanDefinitions() :加載BeanDefinination

createBeanFactory

protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}
           

下面是DefaultListableBeanFactory的建立曆程

spring ioc容器源碼解讀

該過程僅僅是BeanFactory的執行個體化,并設定一些比較公共的配置,不予講解,感興趣的可以自己Debug看看

loadBeanDefinitions

@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 為給定的BeanFactory建立一個XmlBeanDefinitionReader
		// XmlBeanDefinitionReader用于讀取XML并解析為BeanDefinition,并進行注冊
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// 為BeanDefinition的讀取器,配置資源加載器,環境變量,以及EntityResolver(用于判斷)
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}
           

Ⅰ.首先,使用給定的BeanFactory類型的入參,建立一個XmlBeanDefinitionReader

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	//提供了對Document的解析能力,并将解析後的BeanDefinition注冊到BeanDefintionRegistry對象上
	private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
			DefaultBeanDefinitionDocumentReader.class;
	@Nullable
	//處理自定義标簽時候需要使用,它可以通路我們注冊的自定義标簽解析器,完成對自定義标簽的解析
	//預設的實作是DefaultNamespaceHandlerResolver
	private NamespaceHandlerResolver namespaceHandlerResolver;
	//将Resource轉為Document的加載器,純技術SAX技術,無需關心
	private DocumentLoader documentLoader = new DefaultDocumentLoader();
	@Nullable
	private EntityResolver entityResolver;
	private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
			new NamedThreadLocal<>("XML bean definition resources currently being loaded");
	public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
		//直接調用方父類構造器
		super(registry);
	}
}
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
    //用于注冊解析的BeanDefinition(說白了,就是将解析出的BeanDefinition,放到registry裡儲存,以用于bean執行個體化)
	private final BeanDefinitionRegistry registry;
	@Nullable
	//用于加載配置檔案的處理器,它可以将配置及檔案解析為Resourced對象,以用于後面将Resource通過SAX轉為Document對象
	private ResourceLoader resourceLoader;
	@Nullable
	//ApplicationContext的類加載器
	private ClassLoader beanClassLoader;
	//環境變量
	private Environment environment;
	//XmlBeanDefinitionReader的父類AbstractBeanDefinitionReader
	protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		this.registry = registry;
		// 根據傳入的registry,決定ResourceLoader(它是用于加載配置檔案的加載器)
		if (this.registry instanceof ResourceLoader) {
			this.resourceLoader = (ResourceLoader) this.registry;
		}
		else {
			this.resourceLoader = new PathMatchingResourcePatternResolver();
		}
		// 如果可能的話,繼承Environment
		if (this.registry instanceof EnvironmentCapable) {
			this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
		}
		else {
			this.environment = new StandardEnvironment();
		}
	}

}

           

注:從XmlBeanDefinitionReader的構造器參數簽名中,我們發現其實XmlBeanDefinitionReader需要的是一個BeanDefinitionRegistry對象,但是因為我們剛才生成的BeanFactory實作了該接口,故而可以作為入參。

闡釋:真實的構造邏輯在AbstractBeanDefinitionReader中實作的,它将我們傳入的registry,指派給自己的registry屬性上

驗證傳入的這個registry(本例中指的是beanFactory)是否是一個ResourceLoader接口的實作:

  • 如果是:直接将該其指派給resourceLoader屬性
  • 如果否:建立一個PathMatchingResourcePatternResolver對象,然後指派給resourceLoader屬性。本例中的beanFactory是DefaultListableBeanFactory,它并沒有實作ResourceLoader。PathMatchingResourcePatternResolver是對DefaultResourceLoader(它是ResourceLoader的預設實作)的二次封裝,它額外添加了對classpath*:

    或者 war: 或者 */ 等路徑文法的支援!!!

然後驗證傳入的這個registry(即該beanFactory)是否是一個EnvironmentCapable接口的實作:

  • 如果是:則将其指派給environment屬性
  • 如果否:則建立一個StandardEnvironment并指派給environment屬性

PS:ResourceLoader是用于加載資源檔案為Resource對象的,故而對XmlBeanDefinitionReader很重要

Ⅱ. 執行個體化完XmlBeanDefinitionReader,對其進行配置

// 使用該上下文的資源加載環境,來配置XmlBeanDefinitionReader
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		//請注意,這裡對ResourceLoader進行了重新指派,即将this,即ClassPathXmlApplicationContext指派給它
		//ClassPathXmlApplicationContext的父類繼承自DefaultResourceLoader(它是ResourceLoader的預設實作),是以它是一個有效的ResourceLoader
		//多嘴一句,ClassPathXmlApplicationContext并不是直接複用DefaultResourceLoader,而是在其内部初始化了一個PathMatchingResourcePatternResolver類型的resourcePatternResolver變量,在真正加載檔案時,全權交給他,如果是模式比對的,那麼它就處理了,如果并模式比對,那麼再複用這個DefaultResourceLoader。
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// 允許子類提供Reader的自定義初始化(保留給子類使用的)
		initBeanDefinitionReader(beanDefinitionReader);
           

Ⅲ .loadBeanDefinitions(beanDefinitionReader)

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}
           

概述:對ApplicationConext的configLoacations進行for循環,分别交給XmlBeanDefinitionReader單解析

闡述:需要注意的是,我們在最前面講了,ApplicationContext将配置檔案的路徑,存儲在configLocations屬性中。是以在解析BeanDefinition之前,需要先将該配置檔案提取出來,然後交給XmlBeanDefinitionReader去操作(因為XmlBeanDefinitionReader與ApplicationmContext并沒有直接關系,是以無法在運作時擷取到這些配置檔案的資訊)。

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int count = 0;
		for (String location : locations) {
			count += loadBeanDefinitions(location);
		}
		return count;
	}
	@Override
	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}
	public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
	    //還記得為XmlBeanDefinitionReader單獨配置的ResourceLoader嗎??
	    //這裡需要使用它,将configLocation裡的配置檔案路徑,加載解析為Resource資源
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
		}
		if (resourceLoader instanceof ResourcePatternResolver) {
			// 資源的模式比對功能可用.本例子中的resourceLoader是ClassPathXmlApplicationContext,它所實作的ResolveLoader是具有資源模式比對的能力的
			try {
			    //将資源加載的工作委托給resourceLoader
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}
				return count;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// 資源的模式比對功能不可用,隻可以通過絕對URL加載單一資源
			Resource resource = resourceLoader.getResource(location);
			int count = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
			}
			return count;
		}
	}
}
           

注:XmlBeanDefinitionReader是AbstractBeanDefinitionReader的子類

配置檔案資源的加載比較簡單,看上面的注釋即可,接下來着重講解loadBeanDefinitions方法調用

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	@Override
	//對Resource進行編碼
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));
	}
	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}
		//resourcesCurrentlyBeingLoaded中存儲了目前正在被解析的Resource的Set集合,防止同一Resource被多次解析
		//檔案被解析完後,會從Set集合中删除掉
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
		    //擷取編碼後的Resource的檔案流
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
			    //使用InputSourece對InputStream進行封裝(因為SAX值隻識别IputSouce)
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//BeanDefinition加載
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
		    //使用XmlBeanDefinitionReader的類型為DefaultDocumentLoader的documentLoader變量,來将Resource解析為Document
		    //純SAX技術,無需care
			Document doc = doLoadDocument(inputSource, resource);
			//
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
	}
	//提供了對Document的解析能力,并将解析後的BeanDefinition注冊到BeanDefintionRegistry對象上
	private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
			DefaultBeanDefinitionDocumentReader.class;
	@Nullable
	//處理自定義标簽時候需要使用,它可以通路我們注冊的自定義标簽解析器,完成對自定義标簽的解析
	//預設的實作是DefaultNamespaceHandlerResolver
	private NamespaceHandlerResolver namespaceHandlerResolver;
	//将Resource轉為Document的加載器,純技術SAX技術,無需關心
	private DocumentLoader documentLoader = new DefaultDocumentLoader();
	@Nullable
	private EntityResolver entityResolver;
	
	protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
		return BeanUtils.instantiateClass(this.documentReaderClass);
	}
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	    //建立一個可以解析Doument的解析器
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		//使用documentReader完成BeanDefinition的提取,構造和注冊(注冊到BeanDefinitionRegistry上)
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
}
           

這一塊代碼體量較大,但是工作内容很簡單,讀者可以參考我的注釋,腦海裡勾勒粗Spring的處理過程,為了簡答起見,我以直白的表述,闡釋這個過程.:

在前面,我們通過XmlBeanDefinitionReader中的ResourceLoader,将配置檔案解析為Resource,我們先對該Resource做編碼(比如UTF-8等格式的編碼),然後提取該資源的InputStream,最終将其轉換為可以為SAX解析器所識别的InputSource對象。

XmlBeanDefinitionReader中定義了一個類型為DefaultDocumentLoader的documentLoader變量,通過該加載器,可以将InputSource解析為Document對象。

XmlBeanDefinitionReader還定義了一個專門負責解析Document的讀取器,即DefaultBeanDefinitionDocumentReader,我們将前面DocumentLoader解析生成的Document對象傳遞給它,并附帶一個XmlReaderContext對象。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	//建立一個XmlReaderContext,即Xml配置檔案讀取的上下文,用于承載一些讀取、解析Xml配置檔案時
	//所需要使用的一些工具處理器,比如配置檔案的Resource、NamespaceHandlerResolver等
	public XmlReaderContext createReaderContext(Resource resource) {
		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
				this.sourceExtractor, this, getNamespaceHandlerResolver());
	}
	public NamespaceHandlerResolver getNamespaceHandlerResolver() {
		if (this.namespaceHandlerResolver == null) {
			//初始化XmlBeanDefinitionReader時并未設定namespaceHandlerResolver屬性,是以
			//會建立一個NamespaceHandlerResolver的預設實作類:DefaultNamespaceHandlerResolver的執行個體
			this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
		}
		return this.namespaceHandlerResolver;
	}
}
           

注:XmlReaderContext,是Per-Resource的,即一個Resource對應一個Document,而每個Docunent則對用唯一的專用ReaderContext對象。該對象提供了對NamespaceHandlerResolver的通路,使用的是DefaultNamespaceHandlerResolver這個預設實作,當然,這是XmlBeanDefinitionReader在構造它時,為其裝載的)。

具體的BeanDefinition解析邏輯,完全的委托給了DefaultBeanDefinitionDocumentReader,注目觀看:

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}
	protected void doRegisterBeanDefinitions(Element root) {
	    //入參是Document的根元素
	    //DefaultBeanDefinitionDocumentReader将Element元素的解析工作,委托給了BeanDefinitionParserDelegate來負責
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
		//profile驗證
		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
		//模闆方法,實作是空的,由使用者自定義,在真正處理XML解析之前做什麼...
		preProcessXml(root);
		//BeanDefinition核心解析方法
		parseBeanDefinitions(root, this.delegate);
		//模闆方法,實作是空的,由使用者自定義,在真正處理XML解析之前做什麼...
		postProcessXml(root);
		this.delegate = parent;
	}
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//注意:這裡的元素是根節點Element
		//如果delegate判斷該Element是屬于預設命名空間的,那麼取出子節點,循環解析
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					//如果子節點是預設命名空間的元素
					if (delegate.isDefaultNamespace(ele)) {
						//解析預設元素的方法
						parseDefaultElement(ele, delegate);
					}
					else {
						//如果是自定義命名空間的元素,則調用解析自定義元素的方法
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			//如果根元素就是自定義明明空間的元素,則調用解析自定義元素的方法
			delegate.parseCustomElement(root);
		}
	}
	protected BeanDefinitionParserDelegate createDelegate(
			XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {

		BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
		delegate.initDefaults(root, parentDelegate);
		return delegate;
	}

}

           

概述:DefaultBeanDefinitionDocumentReader将Element解析的重任,委托給了BeanDefinitionParserDelegate對象,而它則負責Document中Element的拆解,元素識别以及調用delegate的适當方法做元素的解析,最終生成BeanDefinition對象。

闡釋:DefaultBeanDefinitionDocumentReader在這裡的作用,更像是一個裝備勞工,它購買一個BeanDefinitionParserDelegate機器(該機器可以将Element解析為一個BeanDefinition),然後使用它判斷原料(即Document的根元素)是否是Spring原廠(即Spring預設命名空間)的:

  • 如果該Element是原廠的,那說明是使用Spring的标準配置的配置檔案,那麼先拆解該根元素,取出所有的子元素,for疊代,然後在交給BeanDefinitionParserDelegate來判斷該子元素是否是Spring原廠的(比如Spring所支援的<

    bean />

    元素),如果是原廠支援的,那麼調用parseDefaultElement(element,delegate)做二次解析,畢竟各種元素的處理方法是不一樣的,比如<

    bean />,以及< import

    />等。如果子元素并非Spring原廠支援的,亦即自定義的,那麼完全委托給BeanDefinitionParserDelegate的parseCustomElement()方法去處理

  • 如果子元素并非原廠的,那麼完全委托給BeanDefinitionParserDelegate的parseCustomElement()方法去處理

先看如何加工Spring原廠的Element:

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			//如果該子元素是<import>,那麼先對import内檔案位址解析,即替換掉${...},然後進行beanDefinition的解析工作,這個過程與我們傳給ClassPathXmlApplicationContext的配置檔案的解析過程一毛一樣,也建議讀者自行閱讀源碼
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			//如果該子元素是<alias>,那麼直接在readerContext中的registry上注冊該别名即可
			//實作比較簡單,建議讀者自行閱讀源碼
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			//如果蓋子元素是一個<bean>,那麼完全委托給deleaget去解析
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// 如果該子元素是一個<beans>,那麼遞歸調用doRegisterBeanDefinitions
			doRegisterBeanDefinitions(ele);
		}
	}
}

           

概述:方法很簡單,根據Element的節點名稱,調用不同的方法去解析及注冊

最重要的就是< bean />元素的處理,下面着重描述:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//委托給delegate全權處理element的解析,傳回一個BeanDefinitionHolder
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			//若可以,對BeanDefinitionHolder進行包裝,也是很重要的
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 将最終包裝過的BeanDefinitionHolder,注冊到BeanDefinitionRegistry上
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// 發送注冊消息
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

           

最重要的三個步驟:

  • delegate.parseBeanDefinitionElement(ele);
  • elegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
  • BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,

    getReaderContext().getRegistry());

public class BeanDefinitionParserDelegate {
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		//提取element的id、name 屬性,需要提到的一點是,name屬性也被成為别名,name是支援多值得,格式類似于name="piemon,anokata"
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<>();
		//将name屬性按照分隔符分割開來,并添加到alias清單中
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}
		//将id指派給beanName,校驗:beanNaame不能為空與alias為空不可同時存在
		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isTraceEnabled()) {
				logger.trace("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}
		//beanName唯一性校驗,前面說過,BeanDefinitionParserDelegate是一個有狀态的對象,
		//它使用一個Set<String>類型的usedNames,其中儲存beanName和别名(别名也參與一緻性校驗)
		//實作個很簡單,Set中查找beanName,查到就不滿足唯一性,異常!否則通過
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
		//解析Element元素,生成一個ASbstractBeanDefinition對象(其實真實類型是GenericBeanDefinition,它是AbstractBeanDefinition的子類)
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
					if (logger.isTraceEnabled()) {
						logger.trace("Neither XML 'id' nor 'name' specified - " +
								"using generated bean name [" + beanName + "]");
					}
				}
				catch (Exception ex) {
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			//BeanDefinitionHolder包裝BeanDefinition
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}
		//該方法存在無法解析Element的情況,是以傳回null
		return null;
	}

	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
		//parseState中儲存目前正在被解析的beanName,它是一個棧結構,push/pop
		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		//判斷<bean>中是否有class屬性,如 <bean class="">
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		//判斷<bean>中是否有parent屬性 <bean parent="">
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			//根據className和parent屬性的值,建構AbstractBeanDefinition
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			//解析<bean>中的attribute
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			//給BeanDefinition設定一個用于展示的好看的名字,沒啥鳥用
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
			//解析<bean>中的<meta>子标簽,也被成為元屬性
			parseMetaElements(ele, bd);
			//這兩兩個解析比較重要,分别下列兩種子元素:
			//   <lookup-method name="createCommand" bean="myCommand"/>
			//   <replaced-method name="computeValue" replacer="replacementComputeValue" />
			//這兩個特别有用,用于方法注入,并非setter注入喲~~
			//典型場景:Singleton Bean種使用短周期的Bean(比如Proto/Request/Session等Scope的Bean)
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
			//解析構造器參數,即<bean>中的<construct-arg>子元素
			parseConstructorArgElements(ele, bd);
			//解析<bean>中的<property name="" value="">
			parsePropertyElements(ele, bd);
			//<bean class="example.SimpleMovieCatalog">
        <	//	<qualifier value="main"/> 
    		//</bean> 多用于同類型多Bean的情況
			parseQualifierElements(ele, bd);
			//為BeanDefinition設定Resource,就是此Element所存在于的配置檔案的Resource表現形式
			bd.setResource(this.readerContext.getResource());
			//功能主要是由SourceExtractor負責的,但是我也不知道幹嘛的~~希望讀者有懂得,下面留言指點下
			bd.setSource(extractSource(ele));

			return bd;
		}
		catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		}
		catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		}
		catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		}
		finally {
			//彈出壓入得beanName,表示已經解析完成
			this.parseState.pop();
		}

		return null;
	}
	//new一個BeanDefinition
	protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
			throws ClassNotFoundException {
		//将建立BeanDefinition的任務,交給了BeanDefinitionReaderUtils,并設定其parent屬性以及beanClassName屬性,這些屬性都是參數傳來的!
		return BeanDefinitionReaderUtils.createBeanDefinition(
				parentName, className, this.readerContext.getBeanClassLoader());
	}
}

           

概述:BeanDefinitionParserDelegate是一個有狀态的委托類,用于解析XML格式的配置檔案。parseBeanDefinitionElement(…)方法的作用,是将一個Element,解析成一個BeanDefinition,然後用BeanDefinitionHolder包裝一下。

闡述:看注釋,更清楚

繼續回到Spring原廠元素的解析上,将Element解析為BeanDefinition後,可能還需要包裝它,下面講decorateBeanDefinitionIfRequired:

PS:先看完下面的自定義元素解析(parseCustomerElement),再回頭看這裡的包裝,否則本末倒置了!!!

public class BeanDefinitionParserDelegate {
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
		//交給重載的方法處理
		return decorateBeanDefinitionIfRequired(ele, originalDef, null);
	}
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = originalDef;

		// 首先根據自定義的attribute,進行包裝
		NamedNodeMap attributes = ele.getAttributes();
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// 然後根據内嵌的自定義子元素,進行包裝
		// 需要交代一下,我們前面講過,自定義的元素會交給ddelegate的parseCustomerElemenmt方法解析
		NodeList children = ele.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}
	public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
		//首先擷取元素的命名空間
		String namespaceUri = getNamespaceURI(node);
		//判斷是否是預設的命名空間,Spring的預設命名空進是beans,其他的都不是
		if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
			//如果是自定義的元素,那麼很可能會需要包裝,我們首先解析出該命名空間的NamespaceHandler
			//該NamespaceHandler的具體類型的父類型是一個NamespaceHandlerSupport,它是NamespaceHandler子類
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
			if (handler != null) {
				//每個命名空間都有一個自己的專屬NamespaceHandler,當然這是規範,可以不遵守的
				//每個NamespaceHandler裡都維護着BeanDefinitionParser的Map:parsers和BeanDefinitionDecorator的map:decorators、map:attributeDecorators(不知道怎麼解釋,直白一點,前者包裝<aop:scope-proxy>,即元素級的包裝标簽,後者包裝的是Attribute級的屬性),
				//顧名思義,BeanDefinitionParser是用來解析自定義的元素為BeanDefinition的,
				//而BeanDefinitionDecorator則用來包裝
				BeanDefinitionHolder decorated =
						handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
				if (decorated != null) {
					return decorated;
				}
			}
			else if (namespaceUri.startsWith("http://www.springframework.org/")) {
				error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
			}
			else {
				// A custom namespace, not to be handled by Spring - maybe "xml:...".
				if (logger.isDebugEnabled()) {
					logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
				}
			}
		}
		return originalDef;
	}
}

           

概述:根據Element的命名空間,找到注冊的NamespaceHandlerSupport(他是NamespaceHandler接口的子類),然後找出其上注冊的BeanDefinitionDecorator,用于對BeanDefinition進行包裝。

BeanDefinition的注冊:

public abstract class BeanDefinitionReaderUtils {
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		//首先在beanName下注冊BeanDefinition
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// 然後注冊别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}
}

           

概述:該工具方法先在beanName之下注冊BeanDefinition,然後在想registry注冊其别名嗎,使得對别名的引用亦可以指向所屬的Bean

闡釋:BeanDefinitionRegistry是一個接口,具體的實作是在DefaultListableBeanFactory中實作。

DefaultListableBeanFactory中聲明了一堆的Map,因為他實作了BenaDefinitionRegistry接口,是以他需要具有BeanDefinition的注冊能力,而下面這些Map就是做這個注冊的:

  • beanDefinitionMap:Map<String, BeanDefinition>類型,存儲BeanDefinition
  • beanDefinitionNames:List<String,>類型,存儲beanName
  • frozenBeanDefinitionNames:String[]類型,當機的beanName數組
  • aliasMap:Map<String, String>類型,存儲别名與beanName的映射

    其實可以将BeanDefinitionRegistry,看做是一個記憶體資料庫,所有的BeanDefinition資訊都會記錄在其中,用于Bean執行個體化。

    至此,解析并注冊了BeanDefinition~~

parseCustomerElement

Spring預設的命名空間僅包括beans.xsd所支援的配置項,而像aop、tx、context等命名空間,是屬于自定義的!!!

在我們的配置項中,添加了對于< context annotation-config >,在< bean />中添加了< aop:scoped-proxy/>,這都是自定義的,為此我們着重解釋一下

public class BeanDefinitionParserDelegate {
	public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		//有了Element所歸屬的命名空間(更直白一點,就是我們知道<context annotation-config>是由哪個命名空間定義的)
		//我們就是提取出readerContext(就是XMLReaderContext,我們在上面講過),然後用readerContext中的mamespaceHandlerResolver
		//來對這個命名空間URI進行解析,找出該命名空間的處理器,即NamespaceHandler。
		//此處得到NamespaceHandlerResolver是DefaultNamespaceHandlerResolver類型的,它内部維護這一個handlerMapping,
		//Map<String, Object> handlerMappings;,鍵是命名空間URI,而值則是NamespaceHander或者是class全類名字元串(可以反射生成處理器對象)
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		//将Element交給該NamespaceHandler解析處理
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}
	public String getNamespaceURI(Node node) {
		//Element是Node的子類,Node中聲明了getNamespaceURI()方法,擷取目前節點的命名空間URI
		//對于<context:annotation-config>,他的命名空間URI就是http://www.springframework.org/schema/context,細心的讀者會發現,這是我們在XML上引入的
		return node.getNamespaceURI();
	}
}

           

擷取命名空間URI,然後使用NamespaceHandlerResolver對象,根據命名空間URI,檢出對應的命名空間處理器(NamespaceHandelr),最後将Element委托給該handler解析。

注:NamespaceHandler還要負責注冊解析的BeanDefinition到BeanDefinitionRegistry上

自定義命名空間比較重要,我先解釋一下命名空間、命名空間處理器(NamespaceHandelr)、命名空間URI,不要略過,很簡單的:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
</beans>

           

1.命名空間:xmlns,就是xml命名空間,全稱xml-namespace,對于xmlns:context,他對應的命名空間就是“http://www.springframework.org/schema/context”,但是這個名字太長了,我們就給他一個短小精悍的别名,即context,官方的解釋是,給命名空間提供一個獨一無二的名字。

2.命名空間URI:其實亦可以稱其為命名空間,我麼可以看一下spring-context.xsd定義(Ctrl就能點進去):

<xsd:schema xmlns="http://www.springframework.org/schema/context"
		xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		xmlns:beans="http://www.springframework.org/schema/beans"
		xmlns:tool="http://www.springframework.org/schema/tool"
		##這就是我們context的命名空間
		targetNamespace="http://www.springframework.org/schema/context" 
		elementFormDefault="qualified"
		attributeFormDefault="unqualified">
</xsd:schema>

           

3.NamespaceHandler:xsd中定義了規範,但是規範沒法将這一個個的Element解析成BeanDefinition,這就需要NamespaceHandler登場了,NamespaceHandlerResolver根據命名空間URI,找出其對應的NamespaceHandler,然後讓它去幫我們将Element解析成BeanDefinition

下面我就以spring-context來舉個栗子!!!

衆所周知,< context annotation-config>使得注解變得可能,那麼它是如何實作的呢??我們一步步的看:

  1. 首先是spring-context.xsd,他定義了context命名空間的配置規範,使得我們可以在配置檔案中使用< context annotation-config> < context conponent-scan> < context load-time-weaver>等等。spring-context.xsd隻是一個配置規範,用于限制使用者,大家完全可以把它類比成API接口,公共出服務協定。
  2. 我們最終的目标,是需要解析這些XML配置中的Element,而解析的任務,則是由BeanDefinitionParser接口定義的,Spring的Coder自定義一個AnnotationConfigBeanDefinitionParser類,實作BeanDefinitionParser接口,并在其中添加了對Element的解析邏輯
public class AnnotationConfigBeanDefinitionParser implements BeanDefinitionParser {
	@Override
	@Nullable
	/**
	* parse方法解析Element,并将解析後的BeanDefinition,通過parserContext.getRegistry()傳回的
	* BeanDefinitionRegistry進行注冊。
	* 如果解析後的BanDefinition需要以内嵌的形式被使用,比如被ref屬性引用,那麼傳回必須不能為null
	* 如果解析後的BeanDefinition并不需要以内嵌的形式被使用,那麼可以傳回null
	* 
	* 不得不提的一點是,parserContext是解析上下文,可以與XML配置檔案讀取的XmlReaderContext類比,parserContext引用了readerContext,而readerContext引用了beanfactory(beanFacory可以注冊BeanDefinition,因為他實作了BeanDefinitionRegistry)
	* 和environment(他提供了環境變量和${..}解析)。
	*/
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		Object source = parserContext.extractSource(element);
		// 擷取與該注解相關的BeanPostProcessor的beanDefinition
		Set<BeanDefinitionHolder> processorDefinitions =
				AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
		// 為<context:annotation-config> 建立一個CompositeComponentDefinition對象來表示
		CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
		parserContext.pushContainingComponent(compDefinition);

		// 将上面得到的BeanPostProcessor集合,定義為BeanComponentDefinition,并作為該标簽的CompositeComponentDefinition的内嵌屬性元件,等于聲明了一個元件層級關系
		for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
			parserContext.registerComponent(new BeanComponentDefinition(processorDefinition));
		}
		parserContext.popAndRegisterContainingComponent();
		//因為該注解是屬于配置型的,并沒有Bean會依賴它,是以傳回null
		return null;
	}

}

public abstract class AnnotationConfigUtils {

	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		/**
		* 向BeanDefinitionRegistry注冊了一堆BeanPostProcessor和BeanFactoryPostProcessor,
		* 當然并不是通過調用registerBeanPostProcessor來注冊,而是注冊為BeanDefinition,這樣就成為了配置型的BeanPostProcessor
		* 需要提醒的一點是,Spring将beanPostProcessor/beanFactoryPostFactory分成了兩類,
		* 一類是寫死注冊的,即通過ApplicationContext的addBeanPostProcessor/addBeanFactoryPostFactory,
		* 第二類則是通過配置配置的,即将BeanPostProcess/BeanFactoryPostProcess注冊為BeanDefinition
		* 寫死的優先級,大于任何配置方式的!!!
		*/
		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		//注冊一個beanName = internalConfigurationAnnotationProcessor的BeanDefinition
		//他的原始類型是ConfigurationClassPostProcessor類
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}
	
	private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(beanName, definition);
		return new BeanDefinitionHolder(definition, beanName);
	}
}

           
  1. NamespaceHandelr:AnnotationConfigBeanDefinitionParser更像是建築勞工,而NamespaceHandler則是包工頭。
//一步了然
//當遇見context命名空間中的annotation-config時候,使用AnnotationConfigBeanDefinitionParser來解析
//當遇到context命名空間中的component-scan時候,使用ComponentScanBeanDefinitionParser來解析
public class ContextNamespaceHandler extends NamespaceHandlerSupport {

	@Override
	public void init() {
		registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
		registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
		registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
		registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
	}

}

           
  1. 注冊NamespaceHandler,META-INF檔案夾下,編寫spring.handlers和spring.schemas檔案

    spring.handelrs

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

           

spring.schemas

http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd
http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee.xsd
http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang.xsd
http\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task.xsd
http\://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache.xsd
//
https\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd
https\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee.xsd
https\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang.xsd
https\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task.xsd
https\://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache.xsd
           

Spring遇到自定義的命名空間,比如context,他會首先解析出他的NamespaceURI,也就是http://www.springframework.org/schema/context,然後讓NamespaceHandlerResolver去查找該命名空間的NamespaceHandler,他去查找spring.handlers檔案,就可以找到ContextNamespaceHandler,繼而可以找到annotation-config的BeanDefinitionParser:AnnotationConfigBeanDefinitionParser

  1. 使用,有了這些基礎工作,我們就可以在XML中使用context上下文:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:contexts="http://www.springframework.org/schema/context" ##為該命名空間起一個别名contexts(注意,我們沒有用context,這個名字可以随意改變)
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context					##contexts命名空間的schema位址
        http://www.springframework.org/schema/context/spring-context.xsd">
</beans>       

           

自定義的Element也解析完畢,聽懂了嗎??

prepareBeanFactory

填充BeanFactory屬性

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// 告知BeanFactory使用與ApplicationContext一樣的類加載器
		beanFactory.setBeanClassLoader(getClassLoader());
		//配置SPEL表達式的支援,即#{beanName.field}用法
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		//配置屬性編輯器,我們為什麼可以在配置Bean的時候,用字元串表達數值等的意思??因為PropertyEditor幫我們轉換了
		//<property name="age" value="99">  這裡的99是個int,但是我們依然可以用字元串配置它
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		/**
		* 配置BeanPostProcessor,BeanPostProcessor會在執行個體化Bean的init-method方法之前前後分别
		* 調用其postProcessBeforeInitialization和postProcessAfterInitialization方法
		* 我們可以深入看下ApplicationContextAwareProcessor源碼,截取最重要的片段:
		* 	if (bean instanceof Aware) {
		*   	if (bean instanceof EnvironmentAware) {
		*   		((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		* 		}
		* 		..類比..
		* 	}
		* 其實ApplicationContextAwareProcessor會幫我把幾個特定類型做後置處理,填補上他們需要Aware的東西,
		* 比如上面的EnvironmentAware所想感覺到的Environent
		* 我需要提醒一下,這是寫死的BeanPostProcess,applicationContext維護了一個 beanPostProcessors:List<BeanPostProcessor>,他儲存這些寫死的BeanPostProcessor
		*/
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		//設定Bean執行個體化時所需要忽略的自動裝配的類型,即在依賴注入時,忽略他們
		//結合上面的這個ApplicationContextAwareProcessor,應該知道為什麼了吧??
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);	##Look Here
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		//當注冊了依賴解析後,當你在Bean中,注入了BeanFactory類型的值,或者ApplicationEventPublisher類型的值
		//那麼,便會直接将beanFactory或者this給他注入進去
		//class servier{
		//	@Autowired
		//	private ApplicationEventPublisher publisher;
		//}
		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));
		//如果需要的話,添加AOP
		//<contexts:load-time-weaver />
		//containsBean擷取查找是否有beanName為LOAD_TIME_WEAVER_BEAN_NAME的singleton或者beanDefinition
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// 為類型比對設定一個臨時的類加載器
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// 注冊三個單例的Environment Bean,并設定beanName為environment/systemProperties/systemEnvironment
		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());
		}
	}

           

postProcessBeanFactory

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

           

抽象模闆方法,交給子類去覆寫,到此時,ApplicationContext中的beanFactory已經完全的初始化完,這時候所有的BeanDefinition已經注冊完,但是還沒有執行個體化任何的Bean。此時允許自定義的子類中(就是你自己實作的ApplicationContext類中)去注冊一些特定的BeanPostProcessors。

invokeBeanFactoryPostProcessors

/**
	* 執行個體化并調用所有注冊的BeanFactoryPostProcessors,
	* 如果BeanFactoryPostProcessor又顯式的優先級,那麼必須care
	* 一定要在singleton的bean執行個體化前執行它
	*/
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		//将執行個體化和調用的邏輯,委托給PostProcessorRegistrationDelegate
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
		// 檢測LoadTimeWeaver并為編織做準備,算是有點備援,前面prepareBeanFactory步驟中其實都做了,但是不影響
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}
	//擷取寫死的BeanFactoryPostProcessor,y一定要與配置的BeanFactoryPostProcessor區分開來
	private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}

           

下面先看PostProcessorRegistrationDelegate到底是如何做的:

final class PostProcessorRegistrationDelegate {
	//代碼題很長,但是邏輯很簡單,查找,filter,排序,invoke
	//該方法入參有兩個:
	//beanFactory:不多講了
	//beanFactoryPostProcessors:注意喲,它的值是在AbstractApplicationContext中通過getBeanFactoryPostProcessors()方法
	//擷取的,而beanFactoryPostProcessors是寫死的BeanFactoryPostProcssor的清單(即通過AbstractApplicationContext.addBeanFactoryPostProcessor方法添加進去的)
	//寫死的BeanFactoryPostFacry的優先級是最高的,比任何配置的BeanFactoryPostProcessor要高
	//您可能會問,那配置的寫死的BeanFactoryPostProcessor在哪呢,他在我們的BeanDefinitionRegistry上注冊着呢
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// BanFactoryPostProcessor接口是頂級接口,他的子接口BeanDefinitionRegistryPostProcessors在其上聲明了一個額外的方法
		//即void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
		//我們要先執行BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry這個方法
		//然後在調用這些BanFactoryPostProcessor的postProcessBeanFactory方法
		//但是呢,Spring允許BeanDefinitionRegistryPostProcessors和postProcessBeanFactory的實作具有優先級(即實作Ordered或者PriorityOrdered),其中PriorityOrdered的又要比Ordered優先級高一點,優先級最低的是無序的BeanFactoryPostProcessor

		Set<String> processedBeans = new HashSet<>();
		//如果傳入的BeanFactory執行個體是實作了BeanDefinitionRegistry的話
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			//聲明兩個臨時清單:
			//regularPostProcessors用于存儲正常的BeanFactoryPostProcessor
			//registryProcessors則用于存儲實作自BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			//beanFactoryPostProcessors指的是寫死的BeanFactoryPostProcessor,它的優先級是最高的,故而先執行
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				//如果此寫死的BeanFactoryPostProcessor是實作自BeanDefinitionRegistryPostProcessor,則将其加入到registryProcessors,并執行其特殊的
				//postProcessBeanDefinitionRegistry方法,否則,加入到regularPostProcessors中,并不執行任何方法,等最後再統一執行
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					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, 調用實作了PriorityOrdered的BeanDefinitionRegistryPostProcessors
			//beanFactory.getBeanNamesForType,根據類型,擷取該類型的beanMame
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//如果實作了PriorityOrdered,則将其add到currentRegistryProcessors,等待一會的排序和執行
					//并将beanName加入到processedBeans,以防止同一個bean,被調用多次
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			//對currentRegistryProcessors排序,然後将其add到registryProcessors
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			//調用currentRegistryProcessors中的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//清空currentRegistryProcessors,本人覺得是一種不好的設計
			currentRegistryProcessors.clear();

			// Next, 調用實作了Ordered接口的BeanDefinitionRegistryPostProcessors.
			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, 調用所有其他BeanDefinitionRegistryPostProcessors,知道沒有任何一個BeanDefinitionRegistryPostProcessors出現為止.
			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, 調用到目前為止出現的所有BeanFactoryPostProcessor 的postProcessBeanFactory方法.
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// 調用用上下文執行個體注冊的工廠處理器。即寫死的BeanFactoryPostProcessor
			//因為程式走到這裡,也說明BeanFactory執行個體并非BeanDefinitionRegistry類型,是以優先級什麼的也不care了
			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!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// 分割BeanFactoryPostProcessors,按照PriorityOrdered > Ordered > 其他的順序
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				//跳過,因為這表示該BeanFactoryPostProcessor也是一個BeanDefinitionRegistryPostProcessor,而他已經在前面被處理過了
			}
			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, 調用實作了PriorityOrdered接口的 BeanFactoryPostProcessors .
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, 調用實作了Ordered接口的 BeanFactoryPostProcessors .
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, 調用剩下下的 BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		//清理緩存的merged Bean定義,因為post-processors可能修改了原始中繼資料,例如替換值中的占位符……
		beanFactory.clearMetadataCache();
	}

}

           

概述:在執行個體化singleton的Bean之前,先調用BeanFactoryPostProcessor,以修改BenDifinition。ApplicationContext存在兩種BeanFactoryPostProcessor,一種是寫死的(即通過ApplicationContext的addBeanFactoryPostProcessor方法注冊的),一種是配置的(即通過xml配置的)。先執行寫死的BeanFactoryPostProcessor,Spring允許優先級,同時BeanDefinitionRegistryPostProcessor作為BeanFactoryPostProcessor的子接口,也擁有比純BeanFactoryPostProcessor類型的執行個體更高的優先級。排序與執行,看注釋即可。

registerBeanPostProcessors

//執行個體化并注冊所有BeanPostProcessor的Bean執行個體
	//優先級敏感
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}

final class PostProcessorRegistrationDelegate {
	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// 在BeanPostPorocessor的鍊最開始,注冊一個BeanPostProcessorChecker,他的作用是
		//在bean執行個體窗前的時候,列印日志,比如當:a bean is not eligible for getting processed by all BeanPostProcessors.
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// 将實作了PriorityOrdered、Ordered還有其他的 BeanPostProcessors分隔開來
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		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,注冊實作了 PriorityOrdered 的 BeanPostProcessors.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, 注冊實作了Ordered接口的BeanPostProcessors.
		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,注冊所有的正常BeanPostProcessors.
		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, 重新注冊所有的内置BeanPostProcessors.
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// 重新注冊後置處理器ApplicationListenerDetector,該處理器會檢測實作了ApplicationListener接口的bean,
		// 将其移動到處理器鍊的最後(用于擷取代理等)
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
}

           

概述:代碼較長,但是幹的工作也很簡單,擷取所有配置的BeanPostProcssor,然後按照PriorityOrdered > Ordered > 其他的順序,調用beanFactory.addBeanPostProcessor(postProcessor)方法進行注冊。因為BeanPostProcessor并不在此時執行,是以這裡做的工作隻是執行個體化、注冊。

BeanPostProcessor是在執行個體化Bean時候init-method執行前後才會被調用喲,詳細見Bean加載的講解。

initMessageSource()

國際化相關

initApplicationEventMulticaster()

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	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.isTraceEnabled()) {
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
						"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
			}
		}
	}
	//注冊監聽者
	protected void registerListeners() {
		// 首先注冊靜态指定的監聽者。
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

		// 這裡不初始化FactoryBean:我們需要不初始化所有正常bean,而是讓後置處理程式應用于它們!
		//這裡隻是将beanName注冊到了廣播器上,即注冊配置方式注冊的監聽者的beanName
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// 釋出事件
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
	//廣播事件
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
}

           

概述:如果使用者自定義了事件廣播器,那麼使用使用者定義的,否則使用SimpleApplicationEventMulticaster這個ApplicationEventMulticaster預設實作,來作為applicationEventMulticaster變量的值,并将其注冊到beanFactory的單例緩存中。

onRefresh()

對Web的ApplicationContext至關重要,在特定上下文子類中初始化其他特殊bean。

registerListeners()

protected void registerListeners() {
		// 注冊靜态(寫死)的特定監聽器.
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			//注冊
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

		// 注冊配置的監聽者的BeanName,先不執行個體化他們
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			//注冊
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// 發射一個earlyEvent
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

           

finishBeanFactoryInitialization(beanFactory)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 我目前上下文環境初始化轉換服務,ConversionService
		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));
		}

		//如果此時沒有注冊任何一個解析屬性值的後置處理器, 那麼就注冊一個預設的内嵌屬性值解析器。
		//此時,隻要用于解析注解中的值
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// 盡早初始化LoadTimeWeaverAware bean,以便盡早注冊它們的轉換器。
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		//停止使用臨時類加載器進行類型比對。
		beanFactory.setTempClassLoader(null);

		// 緩存bean的定義(BanDefinition),不會再修改他們了
		beanFactory.freezeConfiguration();

		// 執行個體化所有剩餘的(非lazy-init的)單例。
		beanFactory.preInstantiateSingletons();
	}

           

概述:在該方法中完成BeanFactory的初始化工作,

  1. 首先檢查ConversionService,那段是否有名字

    為"conversionService"或者ConversionService類型的BeanDefinition存在,如果存在,則設定為beanFactory的conversionService變量的值。

  2. 判斷目前的beanFactory是否有内嵌屬性值解析器,如果不存在,則賦一個預設的解析器
  3. 盡早初始化LoadTimeWeaverAware bean,以便盡早注冊它們的轉換器。
  4. 停止對臨時類加載器的使用
  5. 當機所有的beanDefinition,暗示以後不會再修改它們了
  6. 執行個體化所有的單例Bean(排除lazy-init)

finishRefresh()

protected void finishRefresh() {
		// 清理上下文級别的Rsource資源 (such as ASM metadata from scanning).
		clearResourceCaches();

		// 為目前上下文初始化生命周期處理器
		initLifecycleProcessor();

		// 首先将refresh傳播到生命周期處理器上.
		getLifecycleProcessor().onRefresh();

		//發送終極事件.
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}
	protected void initLifecycleProcessor() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		//判斷上下文是否存在“lifecycleProcessor”的BanDefinition
		if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
			this.lifecycleProcessor =
					beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
			}
		}
		else {
			//執行個體化一個預設的生命周期處理器
			DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
			defaultProcessor.setBeanFactory(beanFactory);
			this.lifecycleProcessor = defaultProcessor;
			beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
						"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
			}
		}
	}
public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {
	public void onRefresh() {
		startBeans(true);
		this.running = true;
	}
	private void startBeans(boolean autoStartupOnly) {
		//擷取所有實作了Lifecycle的Ban
		Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
		Map<Integer, LifecycleGroup> phases = new HashMap<>();
		//循環啟動重新整理
		lifecycleBeans.forEach((beanName, bean) -> {
			if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
				int phase = getPhase(bean);
				LifecycleGroup group = phases.get(phase);
				if (group == null) {
					group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
					phases.put(phase, group);
				}
				group.add(beanName, bean);
			}
		});
		if (!phases.isEmpty()) {
			List<Integer> keys = new ArrayList<>(phases.keySet());
			Collections.sort(keys);
			for (Integer key : keys) {
				phases.get(key).start();
			}
		}
	}
	//從目前上下文的底層BeanFactory中擷取所有實作了Lifecycle的Bean
	protected Map<String, Lifecycle> getLifecycleBeans() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		Map<String, Lifecycle> beans = new LinkedHashMap<>();
		String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
		for (String beanName : beanNames) {
			String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
			boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
			String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
			if ((beanFactory.containsSingleton(beanNameToRegister) &&
					(!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
					matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
				Object bean = beanFactory.getBean(beanNameToCheck);
				if (bean != this && bean instanceof Lifecycle) {
					beans.put(beanNameToRegister, (Lifecycle) bean);
				}
			}
		}
		return beans;
	}
}

           

概述:Spring中提供了lifecycle接口,而該接口聲明了start/stop方法,實作此接口的Bean,Spring會在啟動時調用其start方法,在Sring關閉時調用stop方法,以開啟和關閉生命周期。

好了,ioc容器的建立過程就是這個樣子,後面再詳細的寫一下aop的原理與bean的生命周期完善一下就差不多了。其他的細節就需要自己慢慢細看了

參考:

https://blog.csdn.net/qq_31179577/article/details/100693282

https://blog.csdn.net/nuomizhende45/article/details/81158383/