Spring IOC 容器源碼分析——一篇文章讀懂Spring5.x

Spring 設計的初衷

Spring 則立志於全方面的簡化 Java 開發。對此,她主要採取了 4 個關鍵策略: 

1、基於 POJO 的輕量級和最小侵入性編程;

2、通過依賴注入和麪向接口鬆耦合;

3、基於切面和慣性進行聲明式編程;

4、通過切面和模板減少樣板式代碼; 

而他主要是通過:面向 Bean、依賴注入以及面向切面這三種方式來達成的。

Spring5 系統架構

Spring模塊簡介

1.核心容器:

由 spring-beans、spring-core、spring-context 和 spring-expression(Spring Expression Language, SpEL) 4 個模塊組成。

2.AOP 和設備支持

spring-aop、 spring-aspects 和 spring-instrument3 個模塊組成。

3.數據訪問及集成

由 spring-jdbc、 spring-tx、 spring-orm、 spring-jms 和 spring-oxm 5 個模塊組成。

4.Web

由 spring-web、 spring-webmvc、 spring-websocket 和 spring-webflux4 個模塊組成。

5.報文發送

即 spring-messaging模塊。

6.Test:

即 spring-test 模塊。

Spirng 各模塊之間的依賴關係

該圖是 Spring5 的包結構, 可以從中清楚看出 Spring 各個模塊之間的依賴關係。

如果你想加入 Spring 源碼的學習,建議是從 spring-core 入手,其次是 spring-beans 和 spring-aop,隨後是 spring-context,再其次是 spring-tx 和 spring-orm,最後是 spring-web 和其他部分

Spring5 源碼分析

引言

先看下最基本的啓動 Spring 容器的例子

// 用我們的配置文件來啓動一個 ApplicationContext
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

以上代碼就可以利用配置文件來啓動一個 Spring 容器了,引入maven相關依賴。

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
</dependencies>

spring-context 會自動將 spring-core、spring-beans、spring-aop、spring-expression 這幾個基礎 jar 包帶進來。

我們繼續。ApplicationContext context = new ClassPathXmlApplicationContext(...) 其實很好理解,就是在 ClassPath 中尋找 xml 配置文件,根據 xml 文件內容來構建 ApplicationContext。當然,除了 ClassPathXmlApplicationContext 以外,我們也還有其他構建 ApplicationContext 的方案可供選擇,我們先來看看大體的繼承結構是怎麼樣的:

1

我們可以看到,ClassPathXmlApplicationContext 兜兜轉轉了好久纔到 ApplicationContext 接口,同樣的,我們也可以使用綠顏色的

FileSystemXmlApplicationContext 和 AnnotationConfigApplicationContext 這兩個類。

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

AnnotationConfigApplicationContext 是基於註解來使用的,它不需要配置文件,採用 java 配置類和各種註解來配置,是比較簡單的方式,也是大勢所趨吧。

不過本文旨在幫助大家理解整個構建流程,所以決定使用 ClassPathXmlApplicationContext 進行分析。

我們先來一個簡單的例子來看看怎麼實例化 ApplicationContext。

首先,定義一個接口:

public interface MessageService {
    String getMessage();
}

定義接口實現類:

public class MessageServiceImpl implements MessageService {

    public String getMessage() {
        return "hello world";
    }
}

接下來,我們在 resources 目錄新建一個配置文件,文件名隨意,通常叫 application.xml 或 application-xxx.xml 就可以了:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">

    <bean id="messageService" class="com.xuyu.service.impl.MessageServiceImpl"/>
</beans>

這樣,我們就可以跑起來了:

public class App {
    public static void main(String[] args) {
        // 用我們的配置文件來啓動一個 ApplicationContext
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        System.out.println("context 啓動成功");
        // 從 context 中取出我們的 Bean,而不是用 new MessageServiceImpl() 這種方式
        MessageService messageService = context.getBean(MessageService.class);
        // 這句將輸出: hello world
        System.out.println(messageService.getMessage());
    }
}

以上例子很簡單,不過也夠引出本文的主題了,就是怎麼樣通過配置文件來啓動 Spring 的 ApplicationContext?也就是我們今天要分析的 IOC 的核心了。

ApplicationContext 啓動過程中,會負責創建實例 Bean,往各個 Bean 中注入依賴等。

BeanFactory 簡介

BeanFactory,從名字上也很好理解,生產 bean 的工廠,它負責生產和管理各個 bean 實例。

初學者可別以爲我之前說那麼多和 BeanFactory 無關,前面說的 ApplicationContext 其實就是一個 BeanFactory。我們來看下和 BeanFactory 接口相關的主要的繼承結構:

2

我想,大家看完這個圖以後,可能就不是很開心了。ApplicationContext 往下的繼承結構前面一張圖說過了,這裏就不重複了。這張圖呢,背下來肯定是不需要的,有幾個重點和大家說明下就好。

  1. ApplicationContext 繼承了 ListableBeanFactory,這個 Listable 的意思就是,通過這個接口,我們可以獲取多個 Bean,大家看源碼會發現,最頂層 BeanFactory 接口的方法都是獲取單個 Bean 的。
  2. ApplicationContext 繼承了 HierarchicalBeanFactory,Hierarchical 單詞本身已經能說明問題了,也就是說我們可以在應用中起多個 BeanFactory,然後可以將各個 BeanFactory 設置爲父子關係。
  3. AutowireCapableBeanFactory 這個名字中的 Autowire 大家都非常熟悉,它就是用來自動裝配 Bean 用的,但是仔細看上圖,ApplicationContext 並沒有繼承它,不過不用擔心,不使用繼承,不代表不可以使用組合,如果你看到 ApplicationContext 接口定義中的最後一個方法 getAutowireCapableBeanFactory() 就知道了。
  4. ConfigurableListableBeanFactory 也是一個特殊的接口,看圖,特殊之處在於它繼承了第二層所有的三個接口,而 ApplicationContext 沒有。這點之後會用到。
  5. 請先不用花時間在其他的接口和類上,先理解我說的這幾點就可以了。

啓動過程分析

下面將會是冗長的代碼分析,記住,一定要自己打開源碼來看,不然純看是很累的。

第一步,我們肯定要從 ClassPathXmlApplicationContext 的構造方法說起。

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {

	@Nullable
	private Resource[] configResources;

	public ClassPathXmlApplicationContext() {
	}

    // 如果已經有 ApplicationContext 並需要配置成父子關係,那麼調用這個構造方法
	public ClassPathXmlApplicationContext(ApplicationContext parent) {
		super(parent);
	}

	....
    // 根據提供的路徑,處理成配置文件數組(以分號、逗號、空格、tab、換行符分割)
	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			//初始化方法,把所有得Bean都構造一下
			refresh();
		}
	}
...
	public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		Assert.notNull(paths, "Path array must not be null");
		Assert.notNull(clazz, "Class argument must not be null");
		this.configResources = new Resource[paths.length];
		for (int i = 0; i < paths.length; i++) {
			this.configResources[i] = new ClassPathResource(paths[i], clazz);
		}
		refresh();
	}
....
}

接下來,就是 refresh(),這裏簡單說下爲什麼是 refresh(),而不是 init() 這種名字的方法。因爲 ApplicationContext 建立起來以後,其實我們是可以通過調用 refresh() 這個方法重建的,

refresh() 會將原來的 ApplicationContext 銷燬,然後再重新執行一次初始化操作。

往下看,refresh() 方法裏面調用了那麼多方法,就知道肯定不簡單了,請讀者先看個大概,細節之後會詳細說。

spring-context\src\main\java\org\springframework\context\support\AbstractApplicationContext.java

public void refresh() throws BeansException, IllegalStateException {
		// 來個鎖,不然 refresh() 還沒結束,你又來個啓動或銷燬容器的操作,那不就亂套了嘛
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 準備工作,記錄下容器的啓動時間、標記“已啓動”狀態、處理配置文件中的佔位符
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory.
			// 這步比較關鍵,這步完成後,配置文件就會解析成一個個 Bean 定義,註冊到 BeanFactory 中,
			// 當然,這裏說的 Bean 還沒有初始化,只是配置信息都提取出來了,
			// 註冊也只是將這些信息都保存到了註冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 設置 BeanFactory 的類加載器,添加幾個 BeanPostProcessor,手動註冊幾個特殊的 bean
			// 這塊待會會展開說
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 【這裏需要知道 BeanFactoryPostProcessor 這個知識點,Bean 如果實現了此接口,
				// 那麼在容器初始化以後,Spring 會負責調用裏面的 postProcessBeanFactory 方法。】

				// 這裏是提供給子類的擴展點,到這裏的時候,所有的 Bean 都加載、註冊完成了,但是都還沒有初始化
				// 具體的子類可以在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實現類或做點什麼事
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 調用 BeanFactoryPostProcessor 各個實現類的 postProcessBeanFactory(factory) 方法
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 註冊 BeanPostProcessor 的實現類,注意看和 BeanFactoryPostProcessor 的區別
				// 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
				// 兩個方法分別在 Bean 初始化之前和初始化之後得到執行。注意,到這裏 Bean 還沒初始化
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 初始化當前 ApplicationContext 的 MessageSource,國際化這裏就不展開說了,不然沒完沒了了
				initMessageSource();

				// Initialize event multicaster for this context.
				// 初始化當前 ApplicationContext 的事件廣播器,這裏也不展開了
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 從方法名就可以知道,典型的模板方法(鉤子方法),
				// 具體的子類可以在這裏初始化一些特殊的 Bean(在初始化 singleton beans 之前)
				onRefresh();

				// Check for listener beans and register them.
				// 註冊事件監聽器,監聽器需要實現 ApplicationListener 接口。這也不是我們的重點,過
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 重點,重點,重點
				// 初始化所有的 singleton beans
				//(lazy-init 的除外)
				finishBeanFactoryInitialization(beanFactory);

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

			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.
				// 銷燬已經初始化的 singleton 的 Beans,以免有些 bean 會一直佔用資源
				destroyBeans();

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

				// Propagate exception to caller.
				// 把異常往外拋
				throw ex;
			}

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

下面,我們開始一步步來肢解這個 refresh() 方法。

創建 Bean 容器前的準備工作

這個比較簡單,直接看代碼中的幾個註釋即可。

spring-context\src\main\java\org\springframework\context\support\AbstractApplicationContext.java

protected void prepareRefresh() {
		// Switch to active.
		// 記錄啓動時間,
		// 將 active 屬性設置爲 true,closed 屬性設置爲 false,它們都是 AtomicBoolean 類型
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		....
		// Initialize any placeholder property sources in the context environment.
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		// 校驗 xml 配置文件
		getEnvironment().validateRequiredProperties();
        ....
	}

創建 Bean 容器,加載並註冊 Bean

我們回到 refresh() 方法中的下一行 obtainFreshBeanFactory()。

注意,這個方法是全文最重要的部分之一,這裏將會初始化 BeanFactory、加載 Bean、註冊 Bean 等等。

當然,這步結束後,Bean 並沒有完成初始化。這裏指的是 Bean 實例並未在這一步生成。

spring-context\src\main\java\org\springframework\context\support\AbstractApplicationContext.java

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

		// 關閉舊的 BeanFactory (如果有),創建新的 BeanFactory,加載 Bean 定義、註冊 Bean 等等
		refreshBeanFactory();

		// 返回剛剛創建的 BeanFactory
		return getBeanFactory();
	}

進入refreshBeanFactory()這個方法

spring-context\src\main\java\org\springframework\context\support\AbstractRefreshableApplicationContext.java

protected final void refreshBeanFactory() throws BeansException {
		// 如果 ApplicationContext 中已經加載過 BeanFactory 了,銷燬所有 Bean,關閉 BeanFactory
		// 注意,應用中 BeanFactory 本來就是可以多個的,這裏可不是說應用全局是否有 BeanFactory,而是當前
		// ApplicationContext 是否有 BeanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			// 初始化一個 DefaultListableBeanFactory,爲什麼用這個,我們馬上說。
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 用於 BeanFactory 的序列化,我想大部分人應該都用不到
			beanFactory.setSerializationId(getId());
			// 下面這兩個方法很重要,別跟丟了,具體細節之後說
			// 設置 BeanFactory 的兩個配置屬性:是否允許 Bean 覆蓋、是否允許循環引用
			customizeBeanFactory(beanFactory);
			// 加載 Bean 到 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);
		}
	}

看到這裏的時候,我覺得讀者就應該站在高處看 ApplicationContext 了,ApplicationContext 繼承自 BeanFactory,但是它不應該被理解爲 BeanFactory 的實現類,而是說其內部持有一個實例化的 BeanFactory(DefaultListableBeanFactory)。以後所有的 BeanFactory 相關的操作其實是委託給這個實例來處理的

我們說說爲什麼選擇實例化 DefaultListableBeanFactory ?前面我們說了有個很重要的接口 ConfigurableListableBeanFactory,它實現了 BeanFactory 下面一層的所有三個接口,我把之前的繼承圖再拿過來大家再仔細看一下:

3

我們可以看到 ConfigurableListableBeanFactory 只有一個實現類 DefaultListableBeanFactory,而且實現類 DefaultListableBeanFactory 還通過實現右邊的 AbstractAutowireCapableBeanFactory 通吃了右路。所以結論就是,最底下這個傢伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,這也是爲什麼這邊會使用這個類來實例化的原因。

如果你想要在程序運行的時候動態往 Spring IOC 容器註冊新的 bean,就會使用到這個類。那我們怎麼在運行時獲得這個實例呢?

之前我們說過 ApplicationContext 接口能獲取到 AutowireCapableBeanFactory,就是最右上角那個,然後它向下轉型就能得到 DefaultListableBeanFactory 了。

在繼續往下之前,我們需要先了解 BeanDefinition。我們說 BeanFactory 是 Bean 容器,那麼 Bean 又是什麼呢?

這裏的 BeanDefinition 就是我們所說的 Spring 的 Bean,我們自己定義的各個 Bean 其實會轉換成一個個 BeanDefinition 存在於 Spring 的 BeanFactory 中。

所以,如果有人問你 Bean 是什麼的時候,你要知道 Bean 在代碼層面上可以認爲是 BeanDefinition 的實例。

BeanDefinition 中保存了我們的 Bean 信息,比如這個 Bean 指向的是哪個類、是否是單例的、是否懶加載、這個 Bean 依賴了哪些 Bean 等等。

BeanDefinition 接口定義

我們來看下 BeanDefinition 的接口定義:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	
	// 我們可以看到,默認只提供 sington 和 prototype 兩種,
	// 很多讀者可能知道還有 request, session, globalSession, application, websocket 這幾種,
	// 不過,它們屬於基於 web 的擴展。
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

	// 比較不重要,直接跳過吧
	int ROLE_APPLICATION = 0;
	int ROLE_SUPPORT = 1;
	int ROLE_INFRASTRUCTURE = 2;

	// 設置父 Bean,這裏涉及到 bean 繼承,不是 java 繼承。
	// 一句話就是:繼承父 Bean 的配置信息而已
	void setParentName(@Nullable String parentName);

	// 獲取父 Bean
	@Nullable
	String getParentName();

	// 設置 Bean 的類名稱,將來是要通過反射來生成實例的
	void setBeanClassName(@Nullable String beanClassName);
	
	// 獲取 Bean 的類名稱
	@Nullable
	String getBeanClassName();

	// 設置 bean 的 scope
	void setScope(@Nullable String scope);

	@Nullable
	String getScope();
	
	// 設置是否懶加載
	void setLazyInit(boolean lazyInit);

	boolean isLazyInit();

	// 設置該 Bean 依賴的所有的 Bean,注意,這裏的依賴不是指屬性依賴(如 @Autowire 標記的),
	// 是 depends-on="" 屬性設置的值。
	void setDependsOn(@Nullable String... dependsOn);

	// 返回該 Bean 的所有依賴
	@Nullable
	String[] getDependsOn();

	// 設置該 Bean 是否可以注入到其他 Bean 中,只對根據類型注入有效,
	// 如果根據名稱注入,即使這邊設置了 false,也是可以的
	void setAutowireCandidate(boolean autowireCandidate);

	// 該 Bean 是否可以注入到其他 Bean 中
	boolean isAutowireCandidate();

	// 主要的。同一接口的多個實現,如果不指定名字的話,Spring 會優先選擇設置 primary 爲 true 的 bean
	void setPrimary(boolean primary);

	// 是否是 primary 的
	boolean isPrimary();

	// 如果該 Bean 採用工廠方法生成,指定工廠名稱。對工廠不熟悉的讀者
	// 一句話就是:有些實例不是用反射生成的,而是用工廠模式生成的
	void setFactoryBeanName(@Nullable String factoryBeanName);

	// 獲取工廠名稱
	@Nullable
	String getFactoryBeanName();

	// 指定工廠類中的 工廠方法名稱
	void setFactoryMethodName(@Nullable String factoryMethodName);

	// 獲取工廠類中的 工廠方法名稱
	@Nullable
	String getFactoryMethodName();

	// 構造器參數
	ConstructorArgumentValues getConstructorArgumentValues();

	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	// Bean 中的屬性值,後面給 bean 注入屬性值的時候會說到
	MutablePropertyValues getPropertyValues();

	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	void setInitMethodName(@Nullable String initMethodName);
	@Nullable
	String getInitMethodName();
	void setDestroyMethodName(@Nullable String destroyMethodName);
	@Nullable
	String getDestroyMethodName();

	void setRole(int role);
	int getRole();
	void setDescription(@Nullable String description);

	@Nullable
	String getDescription();
	boolean isSingleton();
	boolean isPrototype();

	// 如果這個 Bean 是被設置爲 abstract,那麼不能實例化,
	// 常用於作爲 父bean 用於繼承,其實也很少用......
	boolean isAbstract();

	@Nullable
	String getResourceDescription();
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

}

這個 BeanDefinition 其實已經包含很多的信息了,暫時不清楚所有的方法對應什麼東西沒關係,希望看完本文後讀者可以徹底搞清楚裏面的所有東西。

這裏接口雖然那麼多,但是沒有類似 getInstance() 這種方法來獲取我們定義的類的實例,真正的我們定義的類生成的實例到哪裏去了呢?彆着急,這個要很後面才能講到。

有了 BeanDefinition 的概念以後,我們再往下看 refreshBeanFactory() 方法中的剩餘部分:

spring-context\src\main\java\org\springframework\context\support\AbstractRefreshableApplicationContext.java

refreshBeanFactory()方法中

// 設置 BeanFactory 的兩個配置屬性:是否允許 Bean 覆蓋、是否允許循環引用
 customizeBeanFactory(beanFactory);
// 加載 Bean 到 BeanFactory 中
 loadBeanDefinitions(beanFactory);

雖然只有兩個方法,但路還很長啊。。。

customizeBeanFactory

customizeBeanFactory(beanFactory) 比較簡單,就是配置是否允許 BeanDefinition 覆蓋、是否允許循環引用。

spring-context\src\main\java\org\springframework\context\support\AbstractRefreshableApplicationContext.java

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		// 是否允許 Bean 定義覆蓋
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		// 是否允許 Bean 間的循環依賴
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

BeanDefinition 的覆蓋問題可能會有開發者碰到這個坑,就是在配置文件中定義 bean 時使用了相同的 id 或 name,默認情況下,allowBeanDefinitionOverriding 屬性爲 null,如果在同一配置文件中重複了,會拋錯,但是如果不是同一配置文件中,會發生覆蓋。

循環引用也很好理解:A 依賴 B,而 B 依賴 A。或 A 依賴 B,B 依賴 C,而 C 依賴 A。

默認情況下,Spring 允許循環依賴,當然如果你在 A 的構造方法中依賴 B,在 B 的構造方法中依賴 A 是不行的。

尤其對於覆蓋問題,很多人都希望禁止出現 Bean 覆蓋,可是 Spring 默認是不同文件的時候可以覆蓋的。

之後的源碼中還會出現這兩個屬性,讀者有個印象就可以了。

加載 Bean: loadBeanDefinitions

接下來是最重要的 loadBeanDefinitions(beanFactory) 方法了,這個方法將根據配置,加載各個 Bean,然後放到 BeanFactory 中。

讀取配置的操作在 XmlBeanDefinitionReader 中,其負責加載配置、解析。

spring-context\src\main\java\org\springframework\context\support\AbstractXmlApplicationContext.java

/** 我們可以看到,此方法將通過一個 XmlBeanDefinitionReader 實例來加載各個 Bean。*/
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		// 給這個 BeanFactory 實例化一個 XmlBeanDefinitionReader
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		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.
		// 初始化 BeanDefinitionReader,其實這個是提供給子類覆寫的,
		// 我看了一下,沒有類覆寫這個方法,我們姑且當做不重要吧
		initBeanDefinitionReader(beanDefinitionReader);
		// 重點來了,繼續往下
		loadBeanDefinitions(beanDefinitionReader);
	}

現在還在這個類中,接下來用剛剛初始化的 Reader 開始來加載 xml 配置,這塊代碼讀者可以選擇性跳過,不是很重要。也就是說,下面這個代碼塊,讀者可以很輕鬆地略過。

spring-context\src\main\java\org\springframework\context\support\AbstractXmlApplicationContext.java

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

進入到 loadBeanDefinitions(configResources)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractBeanDefinitionReader.java

// 上面雖然有兩個分支,不過第二個分支很快通過解析路徑轉換爲 Resource 以後也會進到這裏
	@Override
	public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int count = 0;
		// 注意這裏是個 for 循環,也就是每個文件是一個 resource
		for (Resource resource : resources) {
			// 繼續往下看
			count += loadBeanDefinitions(resource);
		}
		// 最後返回 counter,表示總共加載了多少的 BeanDefinition
		return count;
	}

進入 loadBeanDefinitions(resource)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\XmlBeanDefinitionReader.java

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);
		}

		// 用一個 ThreadLocal 來存放配置文件資源
		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 {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				// 核心部分是這裏,往下面看
				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();
			}
		}
	}

進入 doLoadBeanDefinitions(inputSource, encodedResource.getResource())這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\XmlBeanDefinitionReader.java

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			// 這裏就不看了,將 xml 文件轉換爲 Document 對象
			Document doc = doLoadDocument(inputSource, resource);
			// 繼續進入這個方法
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
		....
	}

進入 registerBeanDefinitions(doc, resource)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\XmlBeanDefinitionReader.java

// 返回值:返回從當前配置文件加載了多少數量的 Bean
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		// 這裏點進去
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

進入 registerBeanDefinitions(doc, createReaderContext(resource))方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\DefaultBeanDefinitionDocumentReader.java

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		// 從 xml 根節點開始解析文件
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

經過漫長的鏈路,一個配置文件終於轉換爲一顆 DOM 樹了,注意,這裏指的是其中一個配置文件,不是所有的,讀者可以看到上面有個 for 循環的。下面開始從根節點開始解析:

doRegisterBeanDefinitions:

spring-beans\src\main\java\org\springframework\beans\factory\xml\DefaultBeanDefinitionDocumentReader.java

protected void doRegisterBeanDefinitions(Element root) {
		
		// 我們看名字就知道,BeanDefinitionParserDelegate 必定是一個重要的類,它負責解析 Bean 定義,
		// 這裏爲什麼要定義一個 parent? 看到後面就知道了,是遞歸問題,
		// 因爲 <beans /> 內部是可以定義 <beans /> 的,所以這個方法的 root 其實不一定就是 xml 的根節點,
		// 也可以是嵌套在裏面的 <beans /> 節點,從源碼分析的角度,我們當做根節點就好了
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		if (this.delegate.isDefaultNamespace(root)) {
			// 這塊說的是根節點 <beans ... profile="dev" /> 中的 profile 是否是當前環境需要的,
			// 如果當前環境配置的 profile 不包含此 profile,那就直接 return 了,不對此 <beans /> 解析
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				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;
				}
			}
		}

		//在Bean加載之前做的事情,解析XML把XML中得內容變成BeanDefinition
		preProcessXml(root);// 鉤子
		// 往下看
		parseBeanDefinitions(root, this.delegate);
		//在Bean加載之後做的事情
		postProcessXml(root);// 鉤子

		this.delegate = parent;
	}

preProcessXml(root) 和 postProcessXml(root) 是給子類用的鉤子方法,鑑於沒有被使用到,也不是我們的重點,我們直接跳過。

接下來,看核心解析方法 parseBeanDefinitions(root, this.delegate) :

spring-beans\src\main\java\org\springframework\beans\factory\xml\DefaultBeanDefinitionDocumentReader.java

// default namespace 涉及到的就四個標籤 <import />、<alias />、<bean /> 和 <beans />,
	// 其他的屬於 custom 的
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		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)) {
						// 解析 default namespace 下面的幾個元素
						parseDefaultElement(ele, delegate);
					}
					else {
						// 解析其他 namespace 的元素
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

從上面的代碼,我們可以看到,對於每個配置來說,分別進入到 parseDefaultElement(ele, delegate); 和 delegate.parseCustomElement(ele); 這兩個分支了。

parseDefaultElement(ele, delegate) 代表解析的節點是 <import /><alias /><bean /><beans /> 這幾個。

這裏的四個標籤之所以是 default 的,是因爲它們是處於這個 namespace 下定義的:

http://www.springframework.org/schema/beans

不熟悉 namespace 的讀者請看下面貼出來的 xml,這裏的第二行 xmlns 就是咯。

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-autowire="byName">

而對於其他的標籤,將進入到 delegate.parseCustomElement(element) 這個分支。如我們經常會使用到的 <mvc /><task /><context /><aop />等。

這些屬於擴展,如果需要使用上面這些 ”非 default“ 標籤,那麼上面的 xml 頭部的地方也要引入相應的 namespace 和 .xsd 文件的路徑,如下所示。同時代碼中需要提供相應的 parser 來解析,如 MvcNamespaceHandler、TaskNamespaceHandler、ContextNamespaceHandler、AopNamespaceHandler 等。

假如讀者想分析 <context:property-placeholder location="classpath:xx.properties" /> 的實現原理,就應該到 ContextNamespaceHandler 中找答案。

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

回過神來,看看處理 default 標籤的方法:

進入 parseDefaultElement(ele, delegate)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\DefaultBeanDefinitionDocumentReader.java

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			// 處理 <import /> 標籤
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			// 處理 <alias /> 標籤定義
			// <alias name="fromName" alias="toName"/>
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			// 處理 <bean /> 標籤定義,這也算是我們的重點吧
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// 如果碰到的是嵌套的 <beans /> 標籤,需要遞歸
			doRegisterBeanDefinitions(ele);
		}
	}

如果每個標籤都說,那我不吐血,你們都要吐血了。我們挑我們的重點 <bean /> 標籤出來說。

進入 processBeanDefinition(ele, delegate)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\DefaultBeanDefinitionDocumentReader.java

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 將 <bean /> 節點中的信息提取出來,然後封裝到一個 BeanDefinitionHolder 中,細節往下看
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

		// 下面的幾行先不要看,跳過先,跳過先,跳過先,後面會繼續說的

		if (bdHolder != null) {
			// 如果有自定義屬性的話,進行相應的解析,先忽略
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 我們把這步叫做 註冊Bean 吧
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			// 註冊完成後,發送事件,本文不展開說這個
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

繼續往下看怎麼解析之前,我們先看下 <bean /> 標籤中可以定義哪些屬性:

Property 描述
class 類的全限定名
name 可指定 id、name(用逗號、分號、空格分隔)
scope 作用域
constructor arguments 指定構造參數
properties 設置屬性的值
autowiring mode no(默認值)、byName、byType、 constructor
lazy-initialization mode 是否懶加載(如果被非懶加載的bean依賴了那麼其實也就不能懶加載了)
initialization method bean 屬性設置完成後,會調用這個方法
destruction method bean 銷燬後的回調方法

簡單地說就是像下面這樣子:

<bean id="exampleBean" name="name1, name2, name3" class="com.javadoop.ExampleBean"
      scope="singleton" lazy-init="true" init-method="init" destroy-method="cleanup">

    <!-- 可以用下面三種形式指定構造參數 -->
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg index="0" value="7500000"/>

    <!-- property 的幾種情況 -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

當然,除了上面舉例出來的這些,還有 factory-bean、factory-method、<lockup-method /><replaced-method /><meta /><qualifier /> 這幾個,大家是不是熟悉呢?自己檢驗一下自己對 Spring 中 bean 的瞭解程度。

有了以上這些知識以後,我們再繼續往裏看怎麼解析 bean 元素,是怎麼轉換到 BeanDefinitionHolder 的。

進入到 parseBeanDefinitionElement(ele)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\BeanDefinitionParserDelegate.java

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
		return parseBeanDefinitionElement(ele, null);
	}


public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<>();
		// 將 name 屬性的定義按照 “逗號、分號、空格” 切分,形成一個 別名列表數組,
		// 當然,如果你不定義 name 屬性的話,就是空的了
		// 我在附錄中簡單介紹了一下 id 和 name 的配置,大家可以看一眼,有個20秒就可以了
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
		// 如果沒有指定id, 那麼用別名列表的第一個名字作爲beanName
		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");
			}
		}

		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}

		// 根據 <bean ...>...</bean> 中的配置創建 BeanDefinition,然後把配置中的信息都設置到實例中,
		// 細節後面細說,先知道下面這行結束後,一個 BeanDefinition 實例就出來了。
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		// 到這裏,整個 <bean /> 標籤就算解析結束了,一個 BeanDefinition 就形成了。
		if (beanDefinition != null) {
			// 如果都沒有設置 id 和 name,那麼此時的 beanName 就會爲 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
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

然後,我們再看看怎麼根據配置創建 BeanDefinition 實例的:

進入 parseBeanDefinitionElement(ele, beanName, containingBean)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\BeanDefinitionParserDelegate.java

public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			// 創建 BeanDefinition,然後設置類信息而已,很簡單,就不貼代碼了
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			// 設置 BeanDefinition 的一堆屬性,這些屬性定義在 AbstractBeanDefinition 中
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

			/**
			 * 下面的一堆是解析 <bean>......</bean> 內部的子元素,
			 * 解析出來以後的信息都放到 bd 的屬性中
			 */
			// 解析 <meta />
			parseMetaElements(ele, bd);
			// 解析 <lookup-method />
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			// 解析 <replaced-method />
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			// 解析 <constructor-arg />
			parseConstructorArgElements(ele, bd);
			// 解析 <property />
			parsePropertyElements(ele, bd);
			// 解析 <qualifier />
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
			/**
			 * 到這裏,我們已經完成了根據 <bean /> 配置創建了一個 BeanDefinitionHolder 實例。注意,是一個。
			 * 我們回到解析 <bean /> 的入口方法:
			 */
		}
	.....
	}

到這裏,我們已經完成了根據 <bean /> 配置創建了一個 BeanDefinitionHolder 實例。注意,是一個。

我們回到解析 <bean /> 的入口方法:

進入 processBeanDefinition(ele, delegate)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\xml\DefaultBeanDefinitionDocumentReader.java

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 將 <bean /> 節點中的信息提取出來,然後封裝到一個 BeanDefinitionHolder 中,細節往下看
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

		// 下面的幾行先不要看,跳過先,跳過先,跳過先,後面會繼續說的

		if (bdHolder != null) {
			// 如果有自定義屬性的話,進行相應的解析,先忽略
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 我們把這步叫做 註冊Bean 吧
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			// 註冊完成後,發送事件,本文不展開說這個
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

大家再仔細看一下這塊吧,我們後面就不回來說這個了。這裏已經根據一個 <bean /> 標籤產生了一個 BeanDefinitionHolder 的實例,這個實例裏面也就是一個 BeanDefinition 的實例和它的 beanName、aliases 這三個信息,注意,我們的關注點始終在 BeanDefinition 上:

然後我們準備註冊這個 BeanDefinition,最後,把這個註冊事件發送出去。

下面,我們開始說說註冊 Bean 吧。

註冊 Bean,進入這個方法

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

spring-beans\src\main\java\org\springframework\beans\factory\support\BeanDefinitionReaderUtils.java

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

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		// 註冊這個 Bean
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		// 如果還有別名的話,也要根據別名全部註冊一遍,不然根據別名就會找不到 Bean 了
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				// alias -> beanName 保存它們的別名信息,這個很簡單,用一個 map 保存一下就可以了,
				// 獲取的時候,會先將 alias 轉換爲 beanName,然後再查找
				registry.registerAlias(beanName, alias);
			}
		}
	}

別名註冊的放一邊,畢竟它很簡單,我們看看怎麼註冊 Bean

進入 registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())這個方法中

spring-beans\src\main\java\org\springframework\beans\factory\support\DefaultListableBeanFactory.java

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		// 之後會看到,所有的 Bean 註冊後會放入這個 beanDefinitionMap 中
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		// 處理重複名稱的 Bean 定義的情況
		if (existingDefinition != null) {
			// 還記得 “允許 bean 覆蓋” 這個配置嗎?allowBeanDefinitionOverriding
			// 如果不允許覆蓋的話,拋異常
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				// log...用框架定義的 Bean 覆蓋用戶自定義的 Bean
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			// log...用新的 Bean 覆蓋舊的 Bean
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				// log...用同等的 Bean 覆蓋舊的 Bean,這裏指的是 equals 方法返回 true 的 Bean
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			// 覆蓋
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			// 判斷是否已經有其他的 Bean 開始初始化了.
			// 注意,"註冊Bean" 這個動作結束,Bean 依然還沒有初始化,我們後面會有大篇幅說初始化過程,
			// 在 Spring 容器啓動的最後,會 預初始化 所有的 singleton beans
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				// 最正常的應該是進到這個分支。
				// 將 BeanDefinition 放到這個 map 中,這個 map 保存了所有的 BeanDefinition
				this.beanDefinitionMap.put(beanName, beanDefinition);
				// 這是個 ArrayList,所以會按照 bean 配置的順序保存每一個註冊的 Bean 的名字
				this.beanDefinitionNames.add(beanName);
				// 這是個 LinkedHashSet,代表的是手動註冊的 singleton bean,
				// 注意這裏是 remove 方法,到這裏的 Bean 當然不是手動註冊的
				// 手動指的是通過調用以下方法註冊的 bean :
				// registerSingleton(String beanName, Object singletonObject)
				// 這不是重點,解釋只是爲了不讓大家疑惑。Spring 會在後面"手動"註冊一些 Bean,
				// 如 "environment"、"systemProperties" 等 bean,我們自己也可以在運行時註冊 Bean 到容器中的
				removeManualSingletonName(beanName);
			}
			// 這個不重要,在預初始化的時候會用到,不必管它。
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {

			resetBeanDefinition(beanName);
		}
		/**
		 * 總結一下,到這裏已經初始化了 Bean 容器,<bean /> 配置也相應的轉換爲了一個個 BeanDefinition,
		 * 然後註冊了各個 BeanDefinition 到註冊中心,並且發送了註冊事件。
		 */
	}

總結一下,到這裏已經初始化了 Bean 容器,<bean /> 配置也相應的轉換爲了一個個 BeanDefinition,然後註冊了各個 BeanDefinition 到註冊中心,並且發送了註冊事件。

到這裏是一個分水嶺,前面的內容都還算比較簡單,大家要清楚地知道前面都做了哪些事情。

Bean 容器實例化完成後

說到這裏,我們回到 refresh() 方法,我重新貼了一遍代碼,看看我們說到哪了。是的,我們才說完 obtainFreshBeanFactory() 方法。

考慮到篇幅,這裏開始大幅縮減掉沒必要詳細介紹的部分,大家直接看下面的代碼中的註釋就好了。

public void refresh() throws BeansException, IllegalStateException {
		// 來個鎖,不然 refresh() 還沒結束,你又來個啓動或銷燬容器的操作,那不就亂套了嘛
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 準備工作,記錄下容器的啓動時間、標記“已啓動”狀態、處理配置文件中的佔位符
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory.
			// 這步比較關鍵,這步完成後,配置文件就會解析成一個個 Bean 定義,註冊到 BeanFactory 中,
			// 當然,這裏說的 Bean 還沒有初始化,只是配置信息都提取出來了,
			// 註冊也只是將這些信息都保存到了註冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

/****************************************前面分析了以上源碼*****************************************/

/****************************************下面開始分析後面源碼***************************************/
			// Prepare the bean factory for use in this context.
			// 設置 BeanFactory 的類加載器,添加幾個 BeanPostProcessor,手動註冊幾個特殊的 bean
			// 這塊待會會展開說
			prepareBeanFactory(beanFactory);

			....
	}

準備 Bean 容器: prepareBeanFactory

之前我們說過,Spring 把我們在 xml 配置的 bean 都註冊以後,會"手動"註冊一些特殊的 bean。

這裏簡單介紹下 prepareBeanFactory(factory) 方法:

spring-context\src\main\java\org\springframework\context\support\AbstractApplicationContext.java

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		// 設置 BeanFactory 的類加載器,我們知道 BeanFactory 需要加載類,也就需要類加載器,
		// 這裏設置爲加載當前 ApplicationContext 類的類加載器
		beanFactory.setBeanClassLoader(getClassLoader());
		// 設置 BeanExpressionResolver
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		// 添加一個 BeanPostProcessor,這個 processor 比較簡單:
		// 實現了 Aware 接口的 beans 在初始化的時候,這個 processor 負責回調,
		// 這個我們很常用,如我們會爲了獲取 ApplicationContext 而 implement ApplicationContextAware
		// 注意:它不僅僅回調 ApplicationContextAware,
		//   還會負責回調 EnvironmentAware、ResourceLoaderAware 等,看下源碼就清楚了
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

		// 下面幾行的意思就是,如果某個 bean 依賴於以下幾個接口的實現類,在自動裝配的時候忽略它們,
		// Spring 會通過其他方式來處理這些依賴。
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		/**
		 * 下面幾行就是爲特殊的幾個 bean 賦值,如果有 bean 依賴了以下幾個,會注入這邊相應的值,
		 * 之前我們說過,"當前 ApplicationContext 持有一個 BeanFactory",這裏解釋了第一行
		 * ApplicationContext 還繼承了 ResourceLoader、ApplicationEventPublisher、MessageSource
		 * 所以對於這幾個依賴,可以賦值爲 this,注意 this 是一個 ApplicationContext
		 * 那這裏怎麼沒看到爲 MessageSource 賦值呢?那是因爲 MessageSource 被註冊成爲了一個普通的 bean
		 */
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		// 這個 BeanPostProcessor 也很簡單,在 bean 實例化後,如果是 ApplicationListener 的子類,
		// 那麼將其添加到 listener 列表中,可以理解成:註冊 事件監聽器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		// 這裏涉及到特殊的 bean,名爲:loadTimeWeaver,這不是我們的重點,忽略它
		// tips: ltw 是 AspectJ 的概念,指的是在運行期進行織入,這個和 Spring AOP 不一樣,
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		/**
		 * 從下面幾行代碼我們可以知道,Spring 往往很 "智能" 就是因爲它會幫我們默認註冊一些有用的 bean,
		 * 我們也可以選擇覆蓋
		 */
		// 如果沒有定義 "environment" 這個 bean,那麼 Spring 會 "手動" 註冊一個
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		// 如果沒有定義 "systemProperties" 這個 bean,那麼 Spring 會 "手動" 註冊一個
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		// 如果沒有定義 "systemEnvironment" 這個 bean,那麼 Spring 會 "手動" 註冊一個
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

在上面這塊代碼中,Spring 對一些特殊的 bean 進行了處理,讀者如果暫時還不能消化它們也沒有關係,慢慢往下看。

初始化所有的 singleton beans

我們的重點當然是 finishBeanFactoryInitialization(beanFactory); 這個巨頭了,這裏會負責初始化所有的 singleton beans。

注意,後面的描述中,我都會使用初始化預初始化來代表這個階段,Spring 會在這個階段完成所有的 singleton beans 的實例化。

我們來總結一下,到目前爲止,應該說 BeanFactory 已經創建完成,並且所有的實現了 BeanFactoryPostProcessor 接口的 Bean 都已經初始化並且其中的 postProcessBeanFactory(factory) 方法已經得到回調執行了。而且 Spring 已經“手動”註冊了一些特殊的 Bean,如 ‘environment’、‘systemProperties’ 等。

剩下的就是初始化 singleton beans 了,我們知道它們是單例的,如果沒有設置懶加載,那麼 Spring 會在接下來初始化所有的 singleton beans。

進入refresh()方法中的 finishBeanFactoryInitialization(beanFactory)這個方法

spring-context\src\main\java\org\springframework\context\support\AbstractApplicationContext.java

// 初始化剩餘的 singleton beans
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		// 首先,初始化名字爲 conversionService 的 Bean。 ConversionService,因爲這實在太實用了
		// 什麼,看代碼這裏沒有初始化 Bean 啊!
		// 注意了,初始化的動作包裝在 beanFactory.getBean(...) 中,這裏先不說細節,先往下看吧
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		// 先初始化 LoadTimeWeaverAware 類型的 Bean
		// 之前也說過,這是 AspectJ 相關的內容,放心跳過吧
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		// 沒什麼別的目的,因爲到這一步的時候,Spring 已經開始預初始化 singleton beans 了,
		// 肯定不希望這個時候還出現 bean 定義解析、加載、註冊。凍結
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		// 開始初始化
		beanFactory.preInstantiateSingletons();
		/**
		 * 從上面最後一行往裏看,我們就又回到 DefaultListableBeanFactory 這個類了,這個類大家應該都不陌生了吧。
		 */
	}

從上面最後一行往裏看,我們就又回到 DefaultListableBeanFactory 這個類了,這個類大家應該都不陌生了吧。

preInstantiateSingletons開始初始化了

spring-beans\src\main\java\org\springframework\beans\factory\support\DefaultListableBeanFactory.java

public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// this.beanDefinitionNames 保存了所有的 beanNames
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// 觸發所有的非懶加載的 singleton beans 的初始化操作
		for (String beanName : beanNames) {
			// 合併父 Bean 中的配置,注意 <bean id="" class="" parent="" /> 中的 parent,用的不多吧,
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 非抽象、非懶加載的 singletons。如果配置了 'abstract = true',那是不需要初始化的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				// 處理 FactoryBean(讀者如果不熟悉 FactoryBean
				if (isFactoryBean(beanName)) {
					// FactoryBean 的話,在 beanName 前面加上 ‘&’ 符號。再調用 getBean,getBean 方法別急
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						// 判斷當前 FactoryBean 是否是 SmartFactoryBean 的實現,此處忽略,直接跳過
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							// 對於普通的 Bean,只要調用 getBean(beanName) 這個方法就可以進行初始化了
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		// 到這裏說明所有的非懶加載的 singleton beans 已經完成了初始化
		// 如果我們定義的 bean 是實現了 SmartInitializingSingleton 接口的,那麼在這裏得到回調,忽略
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

接下來,我們就進入到 getBean(beanName) 方法了,這個方法我們經常用來從 BeanFactory 中獲取一個 Bean,而初始化的過程也封裝到了這個方法裏。

getBean

在繼續前進之前,讀者應該具備 FactoryBean 的知識,如果讀者還不熟悉,請移步附錄部分了解 FactoryBean。

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractBeanFactory.java

public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}


// 我們在剖析初始化 Bean 的過程,但是 getBean 方法我們經常是用來從容器中獲取 Bean 用的,注意切換思路,
    // 已經初始化過了就從容器中直接返回,否則就先初始化再返回
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		// 獲取一個 “正統的” beanName,處理兩種情況,一個是前面說的 FactoryBean(前面帶 ‘&’),
		// 一個是別名問題,因爲這個方法是 getBean,獲取 Bean 用的,你要是傳一個別名進來,是完全可以的
		final String beanName = transformedBeanName(name);
		// 注意跟着這個,這個是返回值
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 檢查下是不是已經創建過了
		Object sharedInstance = getSingleton(beanName);
		// 這裏說下 args 唄,雖然看上去一點不重要。前面我們一路進來的時候都是 getBean(beanName),
		// 所以 args 傳參其實是 null 的,但是如果 args 不爲空的時候,那麼意味着調用方不是希望獲取 Bean,而是創建 Bean
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 下面這個方法:如果是普通 Bean 的話,直接返回 sharedInstance,
			// 如果是 FactoryBean 的話,返回它創建的那個實例對象
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 創建過了此 beanName 的 prototype 類型的 bean,那麼拋異常,
			// 往往是因爲陷入了循環引用
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			// 檢查一下這個 BeanDefinition 在容器中是否存在
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				// 如果當前容器不存在這個 BeanDefinition,試試父容器中有沒有
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					// 返回父容器的查詢結果
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			// typeCheckOnly 爲 false,將當前 beanName 放入一個 alreadyCreated 的 Set 集合中。
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			/*
			 * 稍稍總結一下:
			 * 到這裏的話,要準備創建 Bean 了,對於 singleton 的 Bean 來說,容器中還沒創建過此 Bean;
			 * 對於 prototype 的 Bean 來說,本來就是要創建一個新的 Bean。
			 */
			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 先初始化依賴的所有 Bean,這個很好理解。
				// 注意,這裏的依賴指的是 depends-on 中定義的依賴
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						// 檢查是不是有循環依賴,這裏的循環依賴和我們前面說的循環依賴又不一樣,這裏肯定是不允許出現的,不然要亂套了,讀者想一下就知道了
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// 註冊一下依賴關係
						registerDependentBean(dep, beanName);
						try {
							// 先初始化被依賴項
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
				// 如果是 singleton scope 的,創建 singleton 的實例
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 執行創建 Bean,詳情後面再說
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				// 如果是 prototype scope 的,創建 prototype 的實例
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						// 執行創建 Bean
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				// 如果不是 singleton 和 prototype 的話,需要委託給相應的實現類來處理
				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								// 執行創建 Bean
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		// 最後,檢查一下類型對不對,不對的話就拋異常,對的話就返回了
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

大家應該也猜到了,接下來當然是分析 createBean 方法

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException;

第三個參數 args 數組代表創建實例需要的參數,不就是給構造方法用的參數,或者是工廠 Bean 的參數嘛,不過要注意,在我們的初始化階段,args 是 null。

這回我們要到一個新的類了 AbstractAutowireCapableBeanFactory,看類名,AutowireCapable?類名是不是也說明了點問題了。

主要是爲了以下場景,採用 @Autowired 註解注入屬性值:

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java

public class MessageServiceImpl implements MessageService {
    @Autowired
    private UserService userService;

    public String getMessage() {
        return userService.getMessage();
    }
}
<bean id="messageService" class="com.xuyu.example.MessageServiceImpl" />

以上這種屬於混用了 xml 和 註解 兩種方式的配置方式,Spring 會處理這種情況。

好了,讀者要知道這麼回事就可以了,繼續向前。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// 確保 BeanDefinition 中的 Class 被加載
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		// 準備方法覆寫,這裏又涉及到一個概念:MethodOverrides,它來自於 bean 定義中的 <lookup-method />
		// 和 <replaced-method />,如果讀者感興趣,回到 bean 解析的地方看看對這兩個標籤的解析。
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			// 讓 InstantiationAwareBeanPostProcessor 在這一步有機會返回代理,
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			// 重頭戲,創建 bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

創建 Bean

我們繼續往裏看 doCreateBean 這個方法:

進入 doCreateBean(beanName, mbdToUse, args)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// 說明不是 FactoryBean,這裏實例化 Bean,這裏非常關鍵,細節之後再說
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// 這個就是 Bean 裏面的 我們定義的類 的實例,很多地方我直接描述成 "bean 實例"
		final Object bean = instanceWrapper.getWrappedInstance();
		// 類型
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		// 建議跳過吧,涉及接口:MergedBeanDefinitionPostProcessor
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					// MergedBeanDefinitionPostProcessor,這個我真不展開說了,直接跳過吧,很少用的
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 下面這塊代碼是爲了解決循環依賴的問題,以後有時間,我再對循環依賴這個問題進行解析吧
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// 這一步也是非常關鍵的,這一步負責屬性裝配,因爲前面的實例只是實例化了,並沒有設值,這裏就是設值
			populateBean(beanName, mbd, instanceWrapper);
			// 還記得 init-method 嗎?還有 InitializingBean 接口?還有 BeanPostProcessor 接口?
			// 這裏就是處理 bean 初始化完成後的各種回調
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

到這裏,我們已經分析完了 doCreateBean 方法,總的來說,我們已經說完了整個初始化流程。

接下來我們挑 doCreateBean 中的三個細節出來說說。一個是創建 Bean 實例的 createBeanInstance 方法,一個是依賴注入的 populateBean 方法,還有就是回調方法 initializeBean。

注意了,接下來的這三個方法要認真說那也是極其複雜的,很多地方我就點到爲止了,感興趣的讀者可以自己往裏看,最好就是碰到不懂的,自己寫代碼去調試它。

創建 Bean 實例

我們先看看 createBeanInstance 方法。需要說明的是,這個方法如果每個分支都分析下去,必然也是極其複雜冗長的,我們挑重點說。此方法的目的就是實例化我們指定的類。

進入  createBeanInstance(beanName, mbd, args)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 確保已經加載了此 class
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		// 校驗一下這個類的訪問權限
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		if (mbd.getFactoryMethodName() != null) {
			// 採用工廠方法實例化,注意,不是 FactoryBean
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		// 如果不是第一次創建,比如第二次創建 prototype bean。
		// 這種情況下,我們可以從第一次創建知道,採用無參構造函數,還是構造函數依賴注入 來完成實例化
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				// 構造函數依賴注入
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 無參構造函數
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		// 判斷是否採用有參構造函數
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			// 構造函數依賴注入
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		// 調用無參構造函數
		return instantiateBean(beanName, mbd);
	}

挑個簡單的無參構造函數構造實例來看看:

進入instantiateBean(beanName, mbd)方法

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			}
			else {
				// 實例化
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			// 包裝一下,返回
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

我們可以看到,關鍵的地方在於:

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

這裏會進行實際的實例化過程,我們進去看看:

spring-beans\src\main\java\org\springframework\beans\factory\support\SimpleInstantiationStrategy.java

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		// 如果不存在方法覆寫,那就使用 java 反射進行實例化,否則使用 CGLIB
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			// 利用構造方法進行實例化
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			// 存在方法覆寫,利用 CGLIB 來完成實例化,需要依賴於 CGLIB 生成子類,這裏就不展開了。
			// tips: 因爲如果不使用 CGLIB 的話,存在 override 的情況 JDK 並沒有提供相應的實例化支持
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

到這裏,我們就算實例化完成了。我們開始說怎麼進行屬性注入。

bean 屬性注入

看完了 createBeanInstance(...) 方法,我們來看看 populateBean(...) 方法,該方法負責進行屬性設值,處理依賴。

進入 populateBean(beanName, mbd, instanceWrapper)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		// 到這步的時候,bean 實例化完成(通過工廠方法或構造方法),但是還沒開始屬性設值,
		// InstantiationAwareBeanPostProcessor 的實現類可以在這裏對 bean 進行狀態修改,
		// 我也沒找到有實際的使用,所以我們暫且忽略這塊吧
		boolean continueWithPropertyPopulation = true;

		// 如果返回 false,代表不需要進行後續的屬性設值,也不需要再經過其他的 BeanPostProcessor 的處理
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			// 通過名字找到所有屬性值,如果是 bean 依賴,先初始化依賴的 bean。記錄依賴關係
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			// 通過類型裝配。複雜一些
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// 這裏有個非常有用的 BeanPostProcessor 進到這裏: AutowiredAnnotationBeanPostProcessor
					// 對採用 @Autowired、@Value 註解的依賴進行設值,這裏的內容也是非常豐富的,不過本文不會展開說了,感興趣的讀者請自行研究
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			// 設置 bean 實例的屬性值
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

initializeBean

屬性注入完成後,這一步其實就是處理各種回調了,這塊代碼比較簡單。

進入 initializeBean(beanName, exposedObject, mbd)這個方法

spring-beans\src\main\java\org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			// 如果 bean 實現了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回調
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// BeanPostProcessor 的 postProcessBeforeInitialization 回調
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 處理 bean 中定義的 init-method,
			// 或者如果 bean 實現了 InitializingBean 接口,調用 afterPropertiesSet() 方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// BeanPostProcessor 的 postProcessAfterInitialization 回調
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

大家發現沒有,BeanPostProcessor 的兩個回調都發生在這邊,只不過中間處理了 init-method,是不是和讀者原來的認知有點不一樣了?

未完....

原文鏈接:https://javadoop.com/post/spring-ioc#BeanFactory%20%E7%AE%80%E4%BB%8B

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