spring源碼分析(四)
目錄
五、spring源碼分析
--5.5、IOC 容器的高級特性
----1、介紹
----2、Spring IOC 容器的 lazy-init 屬性實現(xiàn)預(yù)實例化
------(1).refresh()
------(2).finishBeanFactoryInitialization 處理預(yù)實例化 Bean
------(3).DefaultListableBeanFactory 對配置 lazy-init 屬性單態(tài) Bean 的預(yù)實例化
----3、FactoryBean 的實現(xiàn)
------(1)FactoryBean的源碼
------(2). AbstractBeanFactory 的 getBean 方法調(diào)用 FactoryBean
------(3).AbstractBeanFactory 生產(chǎn) Bean 實例對象
------(4).工廠 Bean 的實現(xiàn)類 getObject 方法創(chuàng)建 Bean 實例對象
----4、BeanPostProcessor 后置處理器的實現(xiàn)
------(1).BeanPostProcessor 的源碼
------(2).AbstractAutowireCapableBeanFactory 類對容器生成的 Bean 添加后置處理器
------(3).initializeBean 方法為容器產(chǎn)生的 Bean 實例對象添加 BeanPostProcessor 后置處理器
------(4).AdvisorAdapterRegistrationManager 在 Bean 對象初始化后注冊通知適配器
----5、Spring IOC 容器 autowiring 實現(xiàn)原理
------(1). AbstractAutoWireCapableBeanFactory 對 Bean 實例進(jìn)行屬性依賴注入
------(2).Spring IOC 容器根據(jù) Bean 名稱或者類型進(jìn)行 autowiring 自動依賴注入
------(3).DefaultSingletonBeanRegistry 的 registerDependentBean 方法對屬性注入
五、spring源碼分析
5.5、IOC 容器的高級特性
1、介紹
通過前面 4 節(jié)對 Spring IOC 容器的源碼分析,我們已經(jīng)基本上了解了 Spring IOC 容器對 Bean 定 義資源的定位、讀入和解析過程,同時也清楚了當(dāng)用戶通過 getBean 方法向 IOC 容器獲取被管理的 Bean 時,IOC 容器對 Bean 進(jìn)行的初始化和依賴注入過程,這些是 Spring IOC 容器的基本功能特性。 Spring IOC 容器還有一些高級特性,如使用 lazy-init 屬性對 Bean 預(yù)初始化、FactoryBean 產(chǎn)生或者 修飾 Bean 對象的生成、 IOC 容器初始化 Bean 過程中使用 BeanPostProcessor 后置處理器對 Bean 聲明周 期事件管理和 IOC 容器的 autowiring 自動裝配功能等。
2、Spring IOC 容器的 lazy-init 屬性實現(xiàn)預(yù)實例化:
通過前面我們對 IOC 容器的實現(xiàn)和工作原理分析,我們知道 IOC 容器的初始化過程就是對 Bean 定義 資源的定位、載入和注冊,此時容器對 Bean 的依賴注入并沒有發(fā)生,依賴注入主要是在應(yīng)用程序第一 次向容器索取 Bean 時,通過 getBean 方法的調(diào)用完成。
當(dāng) Bean 定義資源的<Bean>元素中配置了 lazy-init 屬性時,容器將會在初始化的時候?qū)λ渲玫?Bean 進(jìn)行預(yù)實例化,Bean 的依賴注入在容器初始化的時候就已經(jīng)完成。這樣,當(dāng)應(yīng)用程序第一次向容器索取 被管理的 Bean 時,就不用再初始化和對 Bean 進(jìn)行依賴注入了,直接從容器中獲取已經(jīng)完成依賴注入的 現(xiàn)成 Bean,可以提高應(yīng)用第一次向容器獲取 Bean 的性能。
下面我們通過代碼分析容器預(yù)實例化的實現(xiàn)過程:
(1).refresh()
先從 IOC 容器的初始會過程開始,通過前面文章分析,我們知道 IOC 容器讀入已經(jīng)定位的 Bean 定義資 源是從 refresh 方法開始的,我們首先從 AbstractApplicationContext 類的 refresh 方法入手分析, 源碼如下:
//容器初始化的過程,讀入 Bean 定義資源,并解析注冊
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//調(diào)用容器準(zhǔn)備刷新的方法,獲取容器的當(dāng)時時間,同時給容器設(shè)置同步標(biāo)識
prepareRefresh();
//告訴子類啟動 refreshBeanFactory()方法,Bean 定義資源文件的載入從
//子類的 refreshBeanFactory()方法啟動
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//為 BeanFactory 配置容器特性,例如類加載器、事件處理器等
prepareBeanFactory(beanFactory);
try {
//為容器的某些子類指定特殊的 BeanPost 事件處理器
postProcessBeanFactory(beanFactory);
//調(diào)用所有注冊的 BeanFactoryPostProcessor 的 Bean
invokeBeanFactoryPostProcessors(beanFactory);
//為 BeanFactory 注冊 BeanPost 事件處理器.
//BeanPostProcessor 是 Bean 后置處理器,用于監(jiān)聽容器觸發(fā)的事件
registerBeanPostProcessors(beanFactory);
//初始化信息源,和國際化相關(guān).
initMessageSource();
//初始化容器事件傳播器.
initApplicationEventMulticaster();
//調(diào)用子類的某些特殊 Bean 初始化方法
onRefresh();
//為事件傳播器注冊事件監(jiān)聽器.
registerListeners();
//這里是對容器 lazy-init 屬性進(jìn)行處理的入口方法
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件處理器,并發(fā)布容器的生命周期事件
finishRefresh();
}catch (BeansException ex) {
//銷毀以創(chuàng)建的單態(tài) Bean
destroyBeans();
//取消 refresh 操作,重置容器的同步標(biāo)識.
cancelRefresh(ex);
throw ex;
}
}
}
在 refresh 方法中 ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory(); 啟動了 Bean 定義資源的載入、注冊過程,而 finishBeanFactoryInitialization 方法是對注冊后的 Bean 定義中的預(yù)實例化(lazy-init=false,Spring 默認(rèn)就是預(yù)實例化,即為 true)的 Bean 進(jìn)行處理的地方。
(2).finishBeanFactoryInitialization 處理預(yù)實例化 Bean:
當(dāng)Bean定義資源被載入IOC容器之后,容器將Bean定義資源解析為容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu)BeanDefinition 注冊到容器中, AbstractApplicationContext 類中的 finishBeanFactoryInitialization 方法對配置了 預(yù)實例化屬性的 Bean 進(jìn)行預(yù)初始化過程,源碼如下:
//對配置了 lazy-init 屬性的 Bean 進(jìn)行預(yù)實例化處理
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//這是 Spring3 以后新加的代碼,為容器指定一個轉(zhuǎn)換服務(wù)(ConversionService)
//在對某些 Bean 屬性進(jìn)行轉(zhuǎn)換時使用
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));
}
//為了類型匹配,停止使用臨時的類加載器
beanFactory.setTempClassLoader(null);
//緩存容器中所有注冊的 BeanDefinition 元數(shù)據(jù),以防被修改
beanFactory.freezeConfiguration();
//對配置了 lazy-init 屬性的單態(tài)模式 Bean 進(jìn)行預(yù)實例化處理
beanFactory.preInstantiateSingletons();
}
ConfigurableListableBeanFactory 是一個接口,其 preInstantiateSingletons 方法由其子類 DefaultListableBeanFactory 提供。
(3).DefaultListableBeanFactory 對配置 lazy-init 屬性單態(tài) Bean 的預(yù)實例化:
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
//在對配置 lazy-init 屬性單態(tài) Bean 的預(yù)實例化過程中,必須多線程同步,以確保數(shù)據(jù)一致性
synchronized (this.beanDefinitionMap) {
for (String beanName : this.beanDefinitionNames) {
//獲取指定名稱的 Bean 定義
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//Bean 不是抽象的,是單態(tài)模式的,且 lazy-init 屬性配置為 false
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果指定名稱的 bean 是創(chuàng)建容器的 Bean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX=”&”,當(dāng) Bean 名稱前面加”&”符號
//時,獲取的是產(chǎn)生容器對象本身,而不是容器產(chǎn)生的 Bean.
//調(diào)用 getBean 方法,觸發(fā)容器對 Bean 實例化和依賴注入過程
final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX +
beanName);
//標(biāo)識是否需要預(yù)實例化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean){
//一個匿名內(nèi)部類
isEagerInit = AccessController.doPrivileged(new
PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean) factory).isEagerInit();
}
}, getAccessControlContext());
}else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)
factory).isEagerInit();
}
if (isEagerInit) {
//調(diào)用 getBean 方法,觸發(fā)容器對 Bean 實例化和依賴注入過程
getBean(beanName);
}
}else {
//調(diào)用 getBean 方法,觸發(fā)容器對 Bean 實例化和依賴注入過程
getBean(beanName);
}
}
}
}
}
通過對 lazy-init 處理源碼的分析,我們可以看出,如果設(shè)置了 lazy-init 屬性,則容器在完成 Bean 定義的注冊之后,會通過 getBean 方法,觸發(fā)對指定 Bean 的初始化和依賴注入過程,這樣當(dāng)應(yīng)用第一 次向容器索取所需的 Bean 時,容器不再需要對 Bean 進(jìn)行初始化和依賴注入,直接從已經(jīng)完成實例化和 依賴注入的 Bean 中取一個現(xiàn)成的 Bean,這樣就提高了第一次獲取 Bean 的性能。
3、FactoryBean 的實現(xiàn):
在 Spring 中,有兩個很容易混淆的類:BeanFactory 和 FactoryBean。
BeanFactory:Bean 工廠,是一個工廠(Factory),我們 Spring IOC 容器的最頂層接口就是這個 BeanFactory,它的作用是管理 Bean,即實例化、定位、配置應(yīng)用程序中的對象及建立這些對象間的依 賴。
FactoryBean:工廠 Bean,是一個 Bean,作用是產(chǎn)生其他 bean 實例。通常情況下,這種 bean 沒有什么 特別的要求,僅需要提供一個工廠方法,該方法用來返回其他 bean 實例。通常情況下,bean 無須自己 實現(xiàn)工廠模式,Spring 容器擔(dān)任工廠角色;但少數(shù)情況下,容器中的 bean 本身就是工廠,其作用是產(chǎn) 生其它 bean 實例。
當(dāng)用戶使用容器本身時,可以使用轉(zhuǎn)義字符”&”來得到 FactoryBean 本身,以區(qū)別通過 FactoryBean 產(chǎn)生的實例對象和 FactoryBean 對象本身。在 BeanFactory 中通過如下代碼定義了該轉(zhuǎn)義字符:
StringFACTORY_BEAN_PREFIX = "&";
如果 myJndiObject 是一個 FactoryBean,則使用&myJndiObject 得到的是 myJndiObject 對象,而不是 myJndiObject 產(chǎn)生出來的對象。
(1).FactoryBean 的源碼:
//工廠 Bean,用于產(chǎn)生其他對象
public interface FactoryBean<T> {
//獲取容器管理的對象實例
T getObject() throws Exception;
//獲取 Bean 工廠創(chuàng)建的對象的類型
Class<?> getObjectType();
//Bean 工廠創(chuàng)建的對象是否是單態(tài)模式,如果是單態(tài)模式,則整個容器中只有一個實例
//對象,每次請求都返回同一個實例對象
boolean isSingleton();
}
(2). AbstractBeanFactory 的 getBean 方法調(diào)用 FactoryBean:
在前面我們分析 Spring IOC 容器實例化 Bean 并進(jìn)行依賴注入過程的源碼時,提到在 getBean 方法觸 發(fā)容器實例化 Bean 的時候會調(diào)用 AbstractBeanFactory 的 doGetBean 方法來進(jìn)行實例化的過程,源碼 如下:
//真正實現(xiàn)向 IOC 容器獲取 Bean 的功能,也是觸發(fā)依賴注入功能的地方
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean
typeCheckOnly) throws BeansException {
//根據(jù)指定的名稱獲取被管理 Bean 的名稱,剝離指定名稱中對容器的相關(guān)依賴
//如果指定的是別名,將別名轉(zhuǎn)換為規(guī)范的 Bean 名稱
final String beanName = transformedBeanName(name);
Object bean;
//先從緩存中取是否已經(jīng)有被創(chuàng)建過的單態(tài)類型的 Bean,對于單態(tài)模式的 Bean 整
//個 IoC 容器中只創(chuàng)建一次,不需要重復(fù)創(chuàng)建
Object sharedInstance = getSingleton(beanName);
//IoC 容器創(chuàng)建單態(tài)模式 Bean 實例對象
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
//如果指定名稱的 Bean 在容器中已有單態(tài)模式的 Bean 被創(chuàng)建,直接返回
//已經(jīng)創(chuàng)建的 Bean
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName
+
"' that is not fully initialized yet - a consequence of a circular
reference");
}else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//獲取給定 Bean 的實例對象,主要是完成 FactoryBean 的相關(guān)處理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
……
}
//獲取給定 Bean 的實例對象,主要是完成 FactoryBean 的相關(guān)處理
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//容器已經(jīng)得到了 Bean 實例對象,這個實例對象可能是一個普通的 Bean,
//也可能是一個工廠 Bean,如果是一個工廠 Bean,則使用它創(chuàng)建一個 Bean 實例對象,
//如果調(diào)用本身就想獲得一個容器的引用,則指定返回這個工廠 Bean 實例對象
//如果指定的名稱是容器的解引用(dereference,即是對象本身而非內(nèi)存地址),
//且 Bean 實例也不是創(chuàng)建 Bean 實例對象的工廠 Bean
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name),
beanInstance.getClass());
}
//如果 Bean 實例不是工廠 Bean,或者指定名稱是容器的解引用,
//調(diào)用者向獲取對容器的引用,則直接返回當(dāng)前的 Bean 實例
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//處理指定名稱不是容器的解引用,或者根據(jù)名稱獲取的 Bean 實例對象是一個工廠 Bean
//使用工廠 Bean 創(chuàng)建一個 Bean 的實例對象
Object object = null;
if (mbd == null) {
//從 Bean 工廠緩存中獲取給定名稱的 Bean 實例對象
object = getCachedObjectForFactoryBean(beanName);
}
//讓 Bean 工廠生產(chǎn)給定名稱的 Bean 對象實例
if (object == null) {
FactoryBean factory = (FactoryBean) beanInstance;
//如果從 Bean 工廠生產(chǎn)的 Bean 是單態(tài)模式的,則緩存
if (mbd == null && containsBeanDefinition(beanName)) {
//從容器中獲取指定名稱的 Bean 定義,如果繼承基類,則合并基類相關(guān)屬性
mbd = getMergedLocalBeanDefinition(beanName);
}
//如果從容器得到 Bean 定義信息,并且 Bean 定義信息不是虛構(gòu)的,
//則讓工廠 Bean 生產(chǎn) Bean 實例對象
boolean synthetic = (mbd != null && mbd.isSynthetic());
//調(diào)用 FactoryBeanRegistrySupport 類的 getObjectFromFactoryBean 方法,
//實現(xiàn)工廠 Bean 生產(chǎn) Bean 對象實例的過程
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
在上面獲取給定 Bean 的實例對象的 getObjectForBeanInstance 方法中,會調(diào)用 FactoryBeanRegistrySupport 類的 getObjectFromFactoryBean 方法,該方法實現(xiàn)了 Bean 工廠生產(chǎn) Bean 實例對象。
Dereference(解引用):一個在 C/C++中應(yīng)用比較多的術(shù)語,在 C++中,”*”是解引用符號,而”&”是 引用符號,解引用是指變量指向的是所引用對象的本身數(shù)據(jù),而不是引用對象的內(nèi)存地址。
(3).AbstractBeanFactory 生產(chǎn) Bean 實例對象:
AbstractBeanFactory 類中生產(chǎn) Bean 實例對象的主要源碼如下
//Bean 工廠生產(chǎn) Bean 實例對象
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean
shouldPostProcess) {
//Bean 工廠是單態(tài)模式,并且 Bean 工廠緩存中存在指定名稱的 Bean 實例對象
if (factory.isSingleton() && containsSingleton(beanName)) {
//多線程同步,以防止數(shù)據(jù)不一致
synchronized (getSingletonMutex()) {
//直接從 Bean 工廠緩存中獲取指定名稱的 Bean 實例對象
Object object = this.factoryBeanObjectCache.get(beanName);
//Bean 工廠緩存中沒有指定名稱的實例對象,則生產(chǎn)該實例對象
if (object == null) {
//調(diào)用 Bean 工廠的 getObject 方法生產(chǎn)指定 Bean 的實例對象
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
//將生產(chǎn)的實例對象添加到 Bean 工廠緩存中
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
}
}
//調(diào)用 Bean 工廠的 getObject 方法生產(chǎn)指定 Bean 的實例對象
else {
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
}
}
//調(diào)用 Bean 工廠的 getObject 方法生產(chǎn)指定 Bean 的實例對象
private Object doGetObjectFromFactoryBean(
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
//實現(xiàn) PrivilegedExceptionAction 接口的匿名內(nèi)置類
//根據(jù) JVM 檢查權(quán)限,然后決定 BeanFactory 創(chuàng)建實例對象
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
//調(diào)用 BeanFactory 接口實現(xiàn)類的創(chuàng)建對象方法
return factory.getObject();
}}, acc);
}catch (PrivilegedActionException pae) {
throw pae.getException();
}
}else {
//調(diào)用 BeanFactory 接口實現(xiàn)類的創(chuàng)建對象方法
object = factory.getObject();
}
}catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation",ex);
}
//創(chuàng)建出來的實例對象為 null,或者因為單態(tài)對象正在創(chuàng)建而返回 null
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
//為創(chuàng)建出來的 Bean 實例對象添加 BeanPostProcessor 后置處理器
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object
failed", ex);
}
}
return object;
}
從上面的源碼分析中,我們可以看出, BeanFactory 接口調(diào)用其實現(xiàn)類的 getObject 方法來實現(xiàn)創(chuàng)建 Bean 實例對象的功能。
(4).工廠 Bean 的實現(xiàn)類 getObject 方法創(chuàng)建 Bean 實例對象:
FactoryBean的實現(xiàn)類有非常多,比如: Proxy、 RMI、 JNDI、 ServletContextFactoryBean 等等, FactoryBean 接口為 Spring 容器提供了一個很好的封裝機(jī)制,具體的 getObject 有不同的實現(xiàn)類根據(jù)不同的實現(xiàn)策 略來具體提供,我們分析一個最簡單的 AnnotationTestFactoryBean 的實現(xiàn)源碼:
public class AnnotationTestBeanFactory implements FactoryBean<IJmxTestBean> {
private final FactoryCreatedAnnotationTestBean instance = new
FactoryCreatedAnnotationTestBean();
public AnnotationTestBeanFactory() {
this.instance.setName("FACTORY");
}
//AnnotationTestBeanFactory 產(chǎn)生 Bean 實例對象的實現(xiàn)
public IJmxTestBean getObject() throws Exception {
return this.instance;
}
public Class<? extends IJmxTestBean> getObjectType() {
return FactoryCreatedAnnotationTestBean.class;
}
public boolean isSingleton() {
return true;
}
}
其他的 Proxy,RMI,JNDI 等等,都是根據(jù)相應(yīng)的策略提供 getObject 的實現(xiàn)。這里不做一一分析,這 已經(jīng)不是 Spring 的核心功能,有需要的時候再去深入研究。
4、BeanPostProcessor 后置處理器的實現(xiàn):
BeanPostProcessor 后置處理器是 Spring IOC 容器經(jīng)常使用到的一個特性,這個 Bean 后置處理器是一 個監(jiān)聽器,可以監(jiān)聽容器觸發(fā)的 Bean 聲明周期事件。后置處理器向容器注冊以后,容器中管理的 Bean 就具備了接收 IOC 容器事件回調(diào)的能力。
BeanPostProcessor 的使用非常簡單,只需要提供一個實現(xiàn)接口 BeanPostProcessor 的實現(xiàn)類,然后在 Bean 的配置文件中設(shè)置即可。
(1).BeanPostProcessor 的源碼:
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
public interface BeanPostProcessor {
//為在 Bean 的初始化前提供回調(diào)入口
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//為在 Bean 的初始化之后提供回調(diào)入口
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
這兩個回調(diào)的入口都是和容器管理的 Bean 的生命周期事件緊密相關(guān),可以為用戶提供在 Spring IOC 容器初始化 Bean 過程中自定義的處理操作。
(2).AbstractAutowireCapableBeanFactory 類對容器生成的 Bean 添加后置處理器:
BeanPostProcessor后置處理器的調(diào)用發(fā)生在Spring IOC容器完成對Bean實例對象的創(chuàng)建和屬性的依 賴注入完成之后,在對 Spring 依賴注入的源碼分析過程中我們知道,當(dāng)應(yīng)用程序第一次調(diào)用 getBean 方法(lazy-init 預(yù)實例化除外)向 Spring IOC 容器索取指定 Bean 時觸發(fā) Spring IOC 容器創(chuàng)建 Bean 實例對象并進(jìn)行依賴注入的過程,其中真正實現(xiàn)創(chuàng)建 Bean 對象并進(jìn)行依賴注入的方法是 AbstractAutowireCapableBeanFactory 類的 doCreateBean 方法,主要源碼如下
//真正創(chuàng)建 Bean 的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
//創(chuàng)建 Bean 實例對象
……
try {
//對 Bean 屬性進(jìn)行依賴注入
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//在對 Bean 實例對象生成和依賴注入完成以后,開始對 Bean 實例對象
//進(jìn)行初始化 ,為 Bean 實例對象應(yīng)用 BeanPostProcessor 后置處理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)
ex).getBeanName())) {
throw (BeanCreationException) ex;
}
……
//為應(yīng)用返回所需要的實例對象
return exposedObject;
}
從上面的代碼中我們知道,為 Bean 實例對象添加 BeanPostProcessor 后置處理器的入口的是 initializeBean 方法。
(3).initializeBean 方法為容器產(chǎn)生的 Bean 實例對象添加 BeanPostProcessor 后置處理器:
同樣在 AbstractAutowireCapableBeanFactory 類中, initializeBean 方法實現(xiàn)為容器創(chuàng)建的 Bean 實例 對象添加 BeanPostProcessor 后置處理器,源碼如下:
//初始容器創(chuàng)建的 Bean 實例對象,為其添加 BeanPostProcessor 后置處理器
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd){
//JDK 的安全機(jī)制驗證權(quán)限
if (System.getSecurityManager() != null) {
//實現(xiàn) PrivilegedAction 接口的匿名內(nèi)部類
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}else {
//為 Bean 實例對象包裝相關(guān)屬性,如名稱,類加載器,所屬容器等信息
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
//對 BeanPostProcessor 后置處理器的 postProcessBeforeInitialization
//回調(diào)方法的調(diào)用,為 Bean 實例初始化前做一些處理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//調(diào)用 Bean 實例對象初始化的方法,這個初始化方法是在 Spring Bean 定義配置
//文件中通過 init-method 屬性指定的
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//對 BeanPostProcessor 后置處理器的 postProcessAfterInitialization
//回調(diào)方法的調(diào)用,為 Bean 實例初始化之后做一些處理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
//調(diào)用 BeanPostProcessor 后置處理器實例對象初始化之前的處理方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍歷容器為所創(chuàng)建的 Bean 添加的所有 BeanPostProcessor 后置處理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//調(diào)用 Bean 實例所有的后置處理中的初始化前處理方法,為 Bean 實例對象在
//初始化之前做一些自定義的處理操作
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
//調(diào)用 BeanPostProcessor 后置處理器實例對象初始化之后的處理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍歷容器為所創(chuàng)建的 Bean 添加的所有 BeanPostProcessor 后置處理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//調(diào)用 Bean 實例所有的后置處理中的初始化后處理方法,為 Bean 實例對象在
//初始化之后做一些自定義的處理操作
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
BeanPostProcessor 是一個接口,其初始化前的操作方法和初始化后的操作方法均委托其實現(xiàn)子類來實 現(xiàn),在 Spring 中,BeanPostProcessor 的實現(xiàn)子類非常的多,分別完成不同的操作,如:AOP 面向切面編程的注冊通知適配器、Bean 對象的數(shù)據(jù)校驗、Bean 繼承屬性/方法的合并等等,我們以最簡單的 AOP 切面織入來簡單了解其主要的功能。
(4).AdvisorAdapterRegistrationManager 在 Bean 對象初始化后注冊通知適配器:
AdvisorAdapterRegistrationManager 是 BeanPostProcessor 的一個實現(xiàn)類,其主要的作用為容器中管 理的 Bean 注冊一個面向切面編程的通知適配器,以便在 Spring 容器為所管理的 Bean 進(jìn)行面向切面編 程時提供方便,其源碼如下:
//為容器中管理的 Bean 注冊一個面向切面編程的通知適配器
public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {
//容器中負(fù)責(zé)管理切面通知適配器注冊的對象
private AdvisorAdapterRegistry advisorAdapterRegistry =
GlobalAdvisorAdapterRegistry.getInstance();
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
//BeanPostProcessor 在 Bean 對象初始化前的操作
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
{
//沒有做任何操作,直接返回容器創(chuàng)建的 Bean 對象
return bean;
}
//BeanPostProcessor 在 Bean 對象初始化后的操作
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
{
if (bean instanceof AdvisorAdapter){
//如果容器創(chuàng)建的 Bean 實例對象是一個切面通知適配器,則向容器的注冊
this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);
}
return bean;
}
}
其他的 BeanPostProcessor 接口實現(xiàn)類的也類似,都是對 Bean 對象使用到的一些特性進(jìn)行處理,或者 向 IOC 容器中注冊,為創(chuàng)建的 Bean 實例對象做一些自定義的功能增加,這些操作是容器初始化 Bean 時 自動觸發(fā)的,不需要認(rèn)為的干預(yù)。
5、Spring IOC 容器 autowiring 實現(xiàn)原理:
Spring IOC 容器提供了兩種管理 Bean 依賴關(guān)系的方式:
a.顯式管理:通過 BeanDefinition 的屬性值和構(gòu)造方法實現(xiàn) Bean 依賴關(guān)系管理。
b.autowiring:Spring IOC 容器的依賴自動裝配功能,不需要對 Bean 屬性的依賴關(guān)系做顯式的聲明, 只需要在配置好 autowiring 屬性,IOC 容器會自動使用反射查找屬性的類型和名稱,然后基于屬性的類 型或者名稱來自動匹配容器中管理的 Bean,從而自動地完成依賴注入。
通過對 autowiring 自動裝配特性的理解,我們知道容器對 Bean 的自動裝配發(fā)生在容器對 Bean 依賴注 入的過程中。在前面對 Spring IOC 容器的依賴注入過程源碼分析中,我們已經(jīng)知道了容器對 Bean 實 例對象的屬性注入的處理發(fā)生在 AbstractAutoWireCapableBeanFactory 類中的 populateBean 方法中, 我們通過程序流程分析 autowiring 的實現(xiàn)原理:
(1). AbstractAutoWireCapableBeanFactory 對 Bean 實例進(jìn)行屬性依賴注入:
應(yīng)用第一次通過 getBean 方法(配置了 lazy-init 預(yù)實例化屬性的除外)向 IoC 容器索取 Bean 時,容器 創(chuàng)建 Bean 實例對象,并且對 Bean 實例對象進(jìn)行屬性依賴注入,AbstractAutoWireCapableBeanFactory 的 populateBean 方法就是實現(xiàn) Bean 屬性依賴注入的功能,其主要源碼如下:
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
//獲取 Bean 定義的屬性值,并對屬性值進(jìn)行處理
PropertyValues pvs = mbd.getPropertyValues();
……
//對依賴注入處理,首先處理 autowiring 自動裝配的依賴注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//根據(jù) Bean 名稱進(jìn)行 autowiring 自動裝配處理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//根據(jù) Bean 類型進(jìn)行 autowiring 自動裝配處理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
}
//對非 autowiring 的屬性進(jìn)行依賴注入處理
……
}
(2).Spring IOC 容器根據(jù) Bean 名稱或者類型進(jìn)行 autowiring 自動依賴注入:
//根據(jù)名稱對屬性進(jìn)行自動依賴注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs){
//對 Bean 對象中非簡單屬性(不是簡單繼承的對象,如 8 中原始類型,字符串,URL 等都是簡單屬性)進(jìn)行處理
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
//如果 Spring IOC 容器中包含指定名稱的 Bean
if (containsBean(propertyName)) {
//調(diào)用 getBean 方法向 IoC 容器索取指定名稱的 Bean 實例,迭代觸發(fā)屬性的初始化和依賴注入
Object bean = getBean(propertyName);
//為指定名稱的屬性賦予屬性值
pvs.add(propertyName, bean);
//指定名稱屬性注冊依賴 Bean 名稱,進(jìn)行屬性依賴注入
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName + "' by name: no matching bean found");
}
}
}
}
//根據(jù)類型對屬性進(jìn)行自動依賴注入
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs)
{
//獲取用戶定義的類型轉(zhuǎn)換器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//存放解析的要注入的屬性
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
//對 Bean 對象中非簡單屬性(不是簡單繼承的對象,如 8 中原始類型,字符
//URL 等都是簡單屬性)進(jìn)行處理
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//獲取指定屬性名稱的屬性描述器
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
//不對 Object 類型的屬性進(jìn)行 autowiring 自動依賴注入
if (!Object.class.equals(pd.getPropertyType())) {
//獲取屬性的 setter 方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
//檢查指定類型是否可以被轉(zhuǎn)換為目標(biāo)對象的類型
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
//創(chuàng)建一個要被注入的依賴描述
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam,
eager);
//根據(jù)容器的 Bean 定義解析依賴關(guān)系,返回所有要被注入的 Bean 對象
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames,
converter);
if (autowiredArgument != null) {
//為屬性賦值所引用的對象
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//指定名稱屬性注冊依賴 Bean 名稱,進(jìn)行屬性依賴注入
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via
property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
//釋放已自動注入的屬性
autowiredBeanNames.clear();
}
}catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName,
propertyName, ex);
}
}
}
通過上面的源碼分析,我們可以看出來通過屬性名進(jìn)行自動依賴注入的相對比通過屬性類型進(jìn)行自動依 賴注入要稍微簡單一些,但是真正實現(xiàn)屬性注入的是 DefaultSingletonBeanRegistry 類的 registerDependentBean 方法。
(3).DefaultSingletonBeanRegistry 的 registerDependentBean 方法對屬性注入:
//為指定的 Bean 注入依賴的 Bean
public void registerDependentBean(String beanName, String dependentBeanName) {
//處理 Bean 名稱,將別名轉(zhuǎn)換為規(guī)范的 Bean 名稱
String canonicalName = canonicalName(beanName);
//多線程同步,保證容器內(nèi)數(shù)據(jù)的一致性
//先從容器中:bean 名稱-->全部依賴 Bean 名稱集合找查找給定名稱 Bean 的依賴 Bean
synchronized (this.dependentBeanMap) {
//獲取給定名稱 Bean 的所有依賴 Bean 名稱
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
//為 Bean 設(shè)置依賴 Bean 信息
dependentBeans = new LinkedHashSet<String>(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
//向容器中:bean 名稱-->全部依賴 Bean 名稱集合添加 Bean 的依賴信息
//即,將 Bean 所依賴的 Bean 添加到容器的集合中
dependentBeans.add(dependentBeanName);
}
//從容器中:bean 名稱-->指定名稱 Bean 的依賴 Bean 集合找查找給定名稱 Bean 的依賴 Bean
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet<String>(8);
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
//向容器中:bean 名稱-->指定 Bean 的依賴 Bean 名稱集合添加 Bean 的依賴信息
//即,將 Bean 所依賴的 Bean 添加到容器的集合中
dependenciesForBean.add(canonicalName);
}
}
通過對 autowiring 的源碼分析,我們可以看出,autowiring 的實現(xiàn)過程:
a.對 Bean 的屬性代調(diào)用 getBean 方法,完成依賴 Bean 的初始化和依賴注入。
b.將依賴 Bean 的屬性引用設(shè)置到被依賴的 Bean 屬性上。
c.將依賴 Bean 的名稱和被依賴 Bean 的名稱存儲在 IOC 容器的集合中。
Spring IOC 容器的 autowiring 屬性自動依賴注入是一個很方便的特性,可以簡化開發(fā)時的配置,但是凡是都有兩面性, 自動屬性依賴注入也有不足,首先,Bean 的依賴關(guān)系在配置文件中無法很清楚地看出來,對于維護(hù)造成一定困難。其 次,由于自動依賴注入是 Spring 容器自動執(zhí)行的,容器是不會智能判斷的,如果配置不當(dāng),將會帶來無法預(yù)料的后果, 所以自動依賴注入特性在使用時還是綜合考慮。