Spring源碼剖析3:懶加載的單例Bean獲取過程分析


轉自【Spring源碼分析】Bean加載流程概覽html

代碼入口

以前寫文章都會囉囉嗦嗦一大堆再開始,進入【Spring源碼分析】這個板塊就直接切入正題了。程序員

不少朋友可能想看Spring源碼,可是不知道應當如何入手去看,這個能夠理解:Java開發者一般從事的都是Java Web的工做,對於程序員來講,一個Web項目用到Spring,只是配置一下配置文件而已,Spring的加載過程相對是不太透明的,不太好去找加載的代碼入口。面試

下面有很簡單的一段代碼能夠做爲Spring代碼加載的入口:spring

<pre> 1 ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
2 ac.getBean(XXX.class);</pre>數據庫

ClassPathXmlApplicationContext用於加載CLASSPATH下的Spring配置文件,能夠看到,第二行就已經能夠獲取到Bean的實例了,那麼必然第一行就已經完成了對全部Bean實例的加載,所以能夠經過ClassPathXmlApplicationContext做爲入口。爲了後面便於代碼閱讀,先給出一下ClassPathXmlApplicationContext這個類的繼承關係:bootstrap

大體的繼承關係是如上圖所示的,因爲版面的關係,沒有繼續畫下去了,左下角的ApplicationContext應當還有一層繼承關係,比較關鍵的一點是它是BeanFactory的子接口。segmentfault

最後聲明一下,本文使用的Spring版本爲3.0.7,比較老,使用這個版本純粹是由於公司使用而已。後端

ClassPathXmlApplicationContext存儲內容數組

爲了更理解ApplicationContext,拿一個實例ClassPathXmlApplicationContext舉例,看一下里面存儲的內容,加深對ApplicationContext的認識,以表格形式展示:緩存

對象名 類 型 做 用 歸屬類
configResources Resource[] 配置文件資源對象數組 ClassPathXmlApplicationContext
configLocations String[] 配置文件字符串數組,存儲配置文件路徑 AbstractRefreshableConfigApplicationContext
beanFactory DefaultListableBeanFactory 上下文使用的Bean工廠 AbstractRefreshableApplicationContext
beanFactoryMonitor Object Bean工廠使用的同步監視器 AbstractRefreshableApplicationContext
id String 上下文使用的惟一Id,標識此ApplicationContext AbstractApplicationContext
parent ApplicationContext 父級ApplicationContext AbstractApplicationContext
beanFactoryPostProcessors List<BeanFactoryPostProcessor> 存儲BeanFactoryPostProcessor接口,Spring提供的一個擴展點 AbstractApplicationContext
startupShutdownMonitor Object refresh方法和destory方法公用的一個監視器,避免兩個方法同時執行 AbstractApplicationContext
shutdownHook Thread Spring提供的一個鉤子,JVM中止執行時會運行Thread裏面的方法 AbstractApplicationContext
resourcePatternResolver ResourcePatternResolver 上下文使用的資源格式解析器 AbstractApplicationContext
lifecycleProcessor LifecycleProcessor 用於管理Bean生命週期的生命週期處理器接口 AbstractApplicationContext
messageSource MessageSource 用於實現國際化的一個接口 AbstractApplicationContext
applicationEventMulticaster ApplicationEventMulticaster Spring提供的事件管理機制中的事件多播器接口 AbstractApplicationContext
applicationListeners Set<ApplicationListener> Spring提供的事件管理機制中的應用監聽器 AbstractApplicationContext

ClassPathXmlApplicationContext構造函數

看下ClassPathXmlApplicationContext的構造函數:

<pre> 1 public ClassPathXmlApplicationContext(String configLocation) throws BeansException { 2 this(new String[] {configLocation}, true, null);
3 }</pre>

複製代碼

<pre>1 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) 2 throws BeansException { 3
4 super(parent); 5 setConfigLocations(configLocations); 6 if (refresh) { 7 refresh(); 8 } 9 }</pre>

複製代碼

從第二段代碼看,總共就作了三件事:

  一、super(parent)

    沒什麼太大的做用,設置一下父級ApplicationContext,這裏是null

  二、setConfigLocations(configLocations)

    代碼就不貼了,一看就知道,裏面作了兩件事情:

    (1)將指定的Spring配置文件的路徑存儲到本地

    (2)解析Spring配置文件路徑中的${PlaceHolder}佔位符,替換爲系統變量中PlaceHolder對應的Value值,System自己就自帶一些系統變量好比class.path、os.name、user.dir等,也能夠經過System.setProperty()方法設置本身須要的系統變量

refresh()

    這個就是整個Spring Bean加載的核心了,它是ClassPathXmlApplicationContext的父類AbstractApplicationContext的一個方法,顧名思義,用於刷新整個Spring上下文信息,定義了整個Spring上下文加載的流程。

refresh方法

上面已經說了,refresh()方法是整個Spring Bean加載的核心,所以看一下整個refresh()方法的定義:

複製代碼

<pre> 1 public void refresh() throws BeansException, IllegalStateException { 2 synchronized (this.startupShutdownMonitor) {
3 // Prepare this context for refreshing.
4 prepareRefresh();
5
6 // Tell the subclass to refresh the internal bean factory.
7 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 8
9 // Prepare the bean factory for use in this context.
10 prepareBeanFactory(beanFactory); 11
12 try { 13 // Allows post-processing of the bean factory in context subclasses.
14 postProcessBeanFactory(beanFactory); 15
16 // Invoke factory processors registered as beans in the context.
17 invokeBeanFactoryPostProcessors(beanFactory); 18
19 // Register bean processors that intercept bean creation.
20 registerBeanPostProcessors(beanFactory); 21
22 // Initialize message source for this context.
23 initMessageSource(); 24
25 // Initialize event multicaster for this context.
26 initApplicationEventMulticaster(); 27
28 // Initialize other special beans in specific context subclasses.
29 onRefresh(); 30
31 // Check for listener beans and register them.
32 registerListeners(); 33
34 // Instantiate all remaining (non-lazy-init) singletons.
35 finishBeanFactoryInitialization(beanFactory); 36
37 // Last step: publish corresponding event.
38 finishRefresh(); 39 } 40
41 catch (BeansException ex) { 42 // Destroy already created singletons to avoid dangling resources.
43 destroyBeans(); 44
45 // Reset 'active' flag.
46 cancelRefresh(ex); 47
48 // Propagate exception to caller.
49 throw ex; 50 } 51 } 52 }</pre>

複製代碼

每一個子方法的功能以後一點一點再分析,首先refresh()方法有幾點是值得咱們學習的:

  一、方法是加鎖的,這麼作的緣由是避免多線程同時刷新Spring上下文

  二、儘管加鎖能夠看到是針對整個方法體的,可是沒有在方法前加synchronized關鍵字,而使用了對象鎖startUpShutdownMonitor,這樣作有兩個好處:

    (1)refresh()方法和close()方法都使用了startUpShutdownMonitor對象鎖加鎖,這就保證了在調用refresh()方法的時候沒法調用close()方法,反之亦然,避免了衝突

    (2)另一個好處不在這個方法中體現,可是提一下,使用對象鎖能夠減少了同步的範圍,只對不能併發的代碼塊進行加鎖,提升了總體代碼運行的效率

  三、方法裏面使用了每一個子方法定義了整個refresh()方法的流程,使得整個方法流程清晰易懂。這點是很是值得學習的,一個方法裏面幾十行甚至上百行代碼寫在一塊兒,在我看來會有三個顯著的問題:

    (1)擴展性下降。反過來說,假使把流程定義爲方法,子類能夠繼承父類,能夠根據須要重寫方法

    (2)代碼可讀性差。很簡單的道理,看代碼的人是願意看一段500行的代碼,仍是願意看10段50行的代碼?

    (3)代碼可維護性差。這點和上面的相似但又有不一樣,可維護性差的意思是,一段幾百行的代碼,功能點不明確,不易後人修改,可能會致使「牽一髮而動全身」

prepareRefresh方法

下面挨個看refresh方法中的子方法,首先是prepareRefresh方法,看一下源碼:

複製代碼

<pre> 1 /**
2 * Prepare this context for refreshing, setting its startup date and
3 * active flag.
4 */
5 protected void prepareRefresh() { 6 this.startupDate = System.currentTimeMillis(); 7 synchronized (this.activeMonitor) {
8 this.active = true;
9 } 10
11 if (logger.isInfoEnabled()) { 12 logger.info("Refreshing " + this); 13 } 14 }</pre>

複製代碼

這個方法功能比較簡單,顧名思義,準備刷新Spring上下文,其功能註釋上寫了:

一、設置一下刷新Spring上下文的開始時間

二、將active標識位設置爲true

另外能夠注意一下12行這句日誌,這句日誌打印了真正加載Spring上下文的Java類。

obtainFreshBeanFactory方法

obtainFreshBeanFactory方法的做用是獲取刷新Spring上下文的Bean工廠,其代碼實現爲:

複製代碼

<pre>1 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 2 refreshBeanFactory(); 3 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 4 if (logger.isDebugEnabled()) { 5 logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); 6 } 7 return beanFactory; 8 }</pre>

複製代碼

其核心是第二行的refreshBeanFactory方法,這是一個抽象方法,有AbstractRefreshableApplicationContext和GenericApplicationContext這兩個子類實現了這個方法,看一下上面ClassPathXmlApplicationContext的繼承關係圖即知,調用的應當是AbstractRefreshableApplicationContext中實現的refreshBeanFactory,其源碼爲:

複製代碼

<pre> 1 protected final void refreshBeanFactory() throws BeansException { 2 if (hasBeanFactory()) { 3 destroyBeans();
4 closeBeanFactory();
5 }
6 try { 7 DefaultListableBeanFactory beanFactory = createBeanFactory(); 8 beanFactory.setSerializationId(getId());
9 customizeBeanFactory(beanFactory); 10 loadBeanDefinitions(beanFactory); 11 synchronized (this.beanFactoryMonitor) { 12 this.beanFactory = beanFactory; 13 } 14 } 15 catch (IOException ex) { 16 throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); 17 } 18 }</pre>

複製代碼

這段代碼的核心是第7行,這行點出了DefaultListableBeanFactory這個類,這個類是構造Bean的核心類,這個類的功能會在下一篇文章中詳細解讀,首先給出DefaultListableBeanFactory的繼承關係圖:

AbstractAutowireCapableBeanFactory這個類的繼承層次比較深,版面有限,就沒有繼續畫下去了,本圖基本上清楚地展現了DefaultListableBeanFactory的層次結構。

爲了更清晰地說明DefaultListableBeanFactory的做用,列舉一下DefaultListableBeanFactory中存儲的一些重要對象及對象中的內容,DefaultListableBeanFactory基本就是操做這些對象,以表格形式說明:

對象名 類 型 做 用 歸屬類
aliasMap Map<String, String> 存儲Bean名稱->Bean別名映射關係 SimpleAliasRegistry
singletonObjects Map<String, Object> 存儲單例Bean名稱->單例Bean實現映射關係 DefaultSingletonBeanRegistry
singletonFactories Map<String, ObjectFactory> 存儲Bean名稱->ObjectFactory實現映射關係 DefaultSingletonBeanRegistry
earlySingletonObjects Map<String, Object> 存儲Bean名稱->預加載Bean實現映射關係 DefaultSingletonBeanRegistry
registeredSingletons Set<String> 存儲註冊過的Bean名 DefaultSingletonBeanRegistry
singletonsCurrentlyInCreation Set<String> 存儲當前正在建立的Bean名 DefaultSingletonBeanRegistry
disposableBeans Map<String, Object> 存儲Bean名稱->Disposable接口實現Bean實現映射關係 DefaultSingletonBeanRegistry
factoryBeanObjectCache Map<String, Object> 存儲Bean名稱->FactoryBean接口Bean實現映射關係 FactoryBeanRegistrySupport
propertyEditorRegistrars Set<PropertyEditorRegistrar> 存儲PropertyEditorRegistrar接口實現集合 AbstractBeanFactory
embeddedValueResolvers List<StringValueResolver> 存儲StringValueResolver(字符串解析器)接口實現列表 AbstractBeanFactory
beanPostProcessors List<BeanPostProcessor> 存儲 BeanPostProcessor接口實現列表 AbstractBeanFactory
mergedBeanDefinitions Map<String, RootBeanDefinition> 存儲Bean名稱->合併過的根Bean定義映射關係 AbstractBeanFactory
alreadyCreated Set<String> 存儲至少被建立過一次的Bean名集合 AbstractBeanFactory
ignoredDependencyInterfaces Set<Class> 存儲不自動裝配的接口Class對象集合 AbstractAutowireCapableBeanFactory
resolvableDependencies Map<Class, Object> 存儲修正過的依賴映射關係 DefaultListableBeanFactory
beanDefinitionMap Map<String, BeanDefinition> 存儲Bean名稱-->Bean定義映射關係 DefaultListableBeanFactory
beanDefinitionNames List<String> 存儲Bean定義名稱列表 DefaultListableBeanFactory

==================================================================================

Spring是如何初始化Bean實例對象

代碼入口

上文【Spring源碼分析】Bean加載流程概覽,比較詳細地分析了Spring上下文加載的代碼入口,而且在AbstractApplicationContext的refresh方法中,點出了finishBeanFactoryInitialization方法完成了對於全部非懶加載的Bean的初始化。

finishBeanFactoryInitialization方法中調用了DefaultListableBeanFactory的preInstantiateSingletons方法,本文針對preInstantiateSingletons進行分析,解讀一下Spring是如何初始化Bean實例對象出來的。

DefaultListableBeanFactory的preInstantiateSingletons方法

DefaultListableBeanFactory的preInstantiateSingletons方法,顧名思義,初始化全部的單例Bean,看一下方法的定義:

複製代碼

<pre> 1 public void preInstantiateSingletons() throws BeansException { 2 if (this.logger.isInfoEnabled()) {
3 this.logger.info("Pre-instantiating singletons in " + this);
4 }
5 synchronized (this.beanDefinitionMap) {
6 // Iterate over a copy to allow for init methods which in turn register new bean definitions. 7 // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
8 List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
9 for (String beanName : beanNames) { 10 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 11 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 12 if (isFactoryBean(beanName)) { 13 final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName); 14 boolean isEagerInit; 15 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 16 isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 17 public Boolean run() { 18 return ((SmartFactoryBean) factory).isEagerInit(); 19 } 20 }, getAccessControlContext()); 21 } 22 else { 23 isEagerInit = (factory instanceof SmartFactoryBean &&
24 ((SmartFactoryBean) factory).isEagerInit()); 25 } 26 if (isEagerInit) { 27 getBean(beanName); 28 } 29 } 30 else { 31 getBean(beanName); 32 } 33 } 34 } 35 } 36 }</pre>

複製代碼

這裏先解釋一下getMergedLocalBeanDefinition方法的含義,由於這個方法會經常看到。Bean定義公共的抽象類是AbstractBeanDefinition,普通的Bean在Spring加載Bean定義的時候,實例化出來的是GenericBeanDefinition,而Spring上下文包括實例化全部Bean用的AbstractBeanDefinition是RootBeanDefinition,這時候就使用getMergedLocalBeanDefinition方法作了一次轉化,將非RootBeanDefinition轉換爲RootBeanDefinition以供後續操做。

解釋完了getMergedLocalBeanDefinition方法的做用,第1行~第10行的代碼就沒什麼好說的了,根據beanName拿到RootBeanDefinition而已。因爲此方法實例化的是全部非懶加載的單例Bean,所以要實例化Bean,必須知足11行的三個定義:

(1)不是抽象的

(2)必須是單例的

(3)必須是非懶加載的

接着簡單看一下第12行~第29行的代碼,這段代碼主要作的是一件事情:首先判斷一下Bean是否FactoryBean的實現,接着判斷Bean是否SmartFactoryBean的實現,假如Bean是SmartFactoryBean的實現而且eagerInit(這個單詞字面意思是渴望加載,找不到一個好的詞語去翻譯,意思就是定義了這個Bean須要當即加載的意思)的話,會當即實例化這個Bean。Java開發人員不須要關注這段代碼,由於SmartFactoryBean基本不會用到,我翻譯一下Spring官網對於SmartFactoryBean的定義描述:

  • FactoryBean接口的擴展接口。接口實現並不表示是否老是返回單獨的實例對象,好比FactoryBean.isSingleton()實現返回false的狀況並不清晰地表示每次返回的都是單獨的實例對象
  • 不實現這個擴展接口的簡單FactoryBean的實現,FactoryBean.isSingleton()實現返回false老是簡單地告訴咱們每次返回的都是單獨的實例對象,暴露出來的對象只可以經過命令訪問
  • 注意:這個接口是一個有特殊用途的接口,主要用於框架內部使用與Spring相關。一般,應用提供的FactoryBean接口實現應當只須要實現簡單的FactoryBean接口便可,新方法應當加入到擴展接口中去

代碼示例

爲了後面的代碼分析方便,事先我定義一個Bean:

複製代碼

<pre> 1 package org.xrq.action; 2
3 import org.springframework.beans.factory.BeanClassLoaderAware; 4 import org.springframework.beans.factory.BeanNameAware; 5 import org.springframework.beans.factory.InitializingBean; 6
7 public class MultiFunctionBean implements InitializingBean, BeanNameAware, BeanClassLoaderAware { 8
9 private int propertyA; 10
11 private int propertyB; 12
13 public int getPropertyA() { 14 return propertyA; 15 } 16
17 public void setPropertyA(int propertyA) { 18 this.propertyA = propertyA; 19 } 20
21 public int getPropertyB() { 22 return propertyB; 23 } 24
25 public void setPropertyB(int propertyB) { 26 this.propertyB = propertyB; 27 } 28
29 public void initMethod() { 30 System.out.println("Enter MultiFunctionBean.initMethod()"); 31 } 32
33 @Override 34 public void setBeanClassLoader(ClassLoader classLoader) { 35 System.out.println("Enter MultiFunctionBean.setBeanClassLoader(ClassLoader classLoader)"); 36 } 37
38 @Override 39 public void setBeanName(String name) { 40 System.out.println("Enter MultiFunctionBean.setBeanName(String name)"); 41 } 42
43 @Override 44 public void afterPropertiesSet() throws Exception { 45 System.out.println("Enter MultiFunctionBean.afterPropertiesSet()"); 46 } 47
48 @Override 49 public String toString() { 50 return "MultiFunctionBean [propertyA=" + propertyA + ", propertyB=" + propertyB + "]"; 51 } 52
53 }</pre>

複製代碼

定義對應的spring.xml:

複製代碼

<pre>1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.or...d">
6
7 <bean id="multiFunctionBean" class="org.xrq.action.MultiFunctionBean" init-method="initMethod" />
8
9 </beans></pre>

複製代碼

利用這個MultiFunctionBean,咱們能夠用來探究Spring加載Bean的多種機制。

doGetBean方法構造Bean流程

上面把getBean以外的代碼都分析了一下,看代碼就能夠知道,獲取Bean對象實例,都是經過getBean方法,getBean方法最終調用的是DefaultListableBeanFactory的父類AbstractBeanFactory類的doGetBean方法,所以這部分重點分析一下doGetBean方法是如何構造出一個單例的Bean的。

doGetBean方法是如何構造出一個單例的Bean

看一下doGetBean方法的代碼實現,比較長:

複製代碼

<pre> 1 protected <T> T doGetBean( 2 final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) 3 throws BeansException { 4
5 final String beanName = transformedBeanName(name); 6 Object bean;
7
8 // Eagerly check singleton cache for manually registered singletons.
9 Object sharedInstance = getSingleton(beanName); 10 if (sharedInstance != null && args == null) {
11 if (logger.isDebugEnabled()) { 12 if (isSingletonCurrentlyInCreation(beanName)) { 13 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
14 "' that is not fully initialized yet - a consequence of a circular reference");
15 }
16 else { 17 logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
18 }
19 }
20 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
21 }
22
23 else { 24 // Fail if we're already creating this bean instance: 25 // We're assumably within a circular reference.
26 if (isPrototypeCurrentlyInCreation(beanName)) { 27 throw new BeanCurrentlyInCreationException(beanName); 28 }
29
30 // Check if bean definition exists in this factory.
31 BeanFactory parentBeanFactory = getParentBeanFactory(); 32 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
33 // Not found -> check parent.
34 String nameToLookup = originalBeanName(name); 35 if (args != null) {
36 // Delegation to parent with explicit args.
37 return (T) parentBeanFactory.getBean(nameToLookup, args); 38 }
39 else { 40 // No args -> delegate to standard getBean method.
41 return parentBeanFactory.getBean(nameToLookup, requiredType); 42 }
43 }
44
45 if (!typeCheckOnly) {
46 markBeanAsCreated(beanName);
47 }
48
49 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 50 checkMergedBeanDefinition(mbd, beanName, args);
51
52 // Guarantee initialization of beans that the current bean depends on.
53 String[] dependsOn = mbd.getDependsOn(); 54 if (dependsOn != null) {
55 for (String dependsOnBean : dependsOn) { 56 getBean(dependsOnBean);
57 registerDependentBean(dependsOnBean, beanName);
58 }
59 }
60
61 // Create bean instance.
62 if (mbd.isSingleton()) { 63 sharedInstance = getSingleton(beanName, new ObjectFactory() { 64 public Object getObject() throws BeansException { 65 try { 66 return createBean(beanName, mbd, args); 67 }
68 catch (BeansException ex) { 69 // Explicitly remove instance from singleton cache: It might have been put there 70 // eagerly by the creation process, to allow for circular reference resolution. 71 // Also remove any beans that received a temporary reference to the bean.
72 destroySingleton(beanName);
73 throw ex; 74 }
75 }
76 });
77 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 78 }
79
80 else if (mbd.isPrototype()) { 81 // It's a prototype -> create a new instance.
82 Object prototypeInstance = null;
83 try { 84 beforePrototypeCreation(beanName);
85 prototypeInstance = createBean(beanName, mbd, args); 86 }
87 finally { 88 afterPrototypeCreation(beanName);
89 }
90 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 91 }
92
93 else { 94 String scopeName = mbd.getScope(); 95 final Scope scope = this.scopes.get(scopeName);
96 if (scope == null) {
97 throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
98 }
99 try { 100 Object scopedInstance = scope.get(beanName, new ObjectFactory() { 101 public Object getObject() throws BeansException { 102 beforePrototypeCreation(beanName); 103 try { 104 return createBean(beanName, mbd, args); 105 } 106 finally { 107 afterPrototypeCreation(beanName); 108 } 109 } 110 }); 111 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 112 } 113 catch (IllegalStateException ex) { 114 throw new BeanCreationException(beanName, 115 "Scope '" + scopeName + "' is not active for the current thread; " +
116 "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", 117 ex); 118 } 119 } 120 } 121
122 // Check if required type matches the type of the actual bean instance.
123 if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { 124 try { 125 return getTypeConverter().convertIfNecessary(bean, requiredType); 126 } 127 catch (TypeMismatchException ex) { 128 if (logger.isDebugEnabled()) { 129 logger.debug("Failed to convert bean '" + name + "' to required type [" +
130 ClassUtils.getQualifiedName(requiredType) + "]", ex); 131 } 132 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 133 } 134 } 135 return (T) bean; 136 }</pre>

複製代碼

首先第9行~第21行的代碼,第9行的代碼就不進去看了,簡單說一下:首先檢查一下本地的單例緩存是否已經加載過Bean,沒有的話再檢查earlySingleton緩存是否已經加載過Bean(又是early,很差找到詞語翻譯),沒有的話執行後面的邏輯。

接着第26行~第50行,這裏執行的都是一些基本的檢查和簡單的操做,包括bean是不是prototype的(prototype的Bean當前建立會拋出異常)、是否抽象的、將beanName加入alreadyCreated這個Set中等。

接着第53行~第59行,咱們常常在bean標籤中看到depends-on這個屬性,就是經過這段保證了depends-on依賴的Bean會優先於當前Bean被加載。

接着第62行~第78行、第80行~第91行、第93行~第120行有三個判斷,顯然上面的MultiFunctionBean是一個單例的Bean也是本文探究的重點,所以執行第62行~第78行的邏輯。getSingleton方法不貼了,有一些前置的判斷,很簡單的邏輯,重點就是調用了ObjectFactory的getObject()方法來獲取到單例Bean對象,方法的實現是調用了createBean方法,createBean方法是AbstractBeanFactory的子類AbstractAutowireCapableBeanFactory的一個方法,看一下它的方法實現:

複製代碼

<pre> 1 protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 2 throws BeanCreationException { 3
4 if (logger.isDebugEnabled()) { 5 logger.debug("Creating instance of bean '" + beanName + "'");
6 }
7 // Make sure bean class is actually resolved at this point.
8 resolveBeanClass(mbd, beanName);
9
10 // Prepare method overrides.
11 try { 12 mbd.prepareMethodOverrides(); 13 } 14 catch (BeanDefinitionValidationException ex) { 15 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), 16 beanName, "Validation of method overrides failed", ex); 17 } 18
19 try { 20 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
21 Object bean = resolveBeforeInstantiation(beanName, mbd); 22 if (bean != null) { 23 return bean; 24 } 25 } 26 catch (Throwable ex) { 27 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 28 "BeanPostProcessor before instantiation of bean failed", ex); 29 } 30
31 Object beanInstance = doCreateBean(beanName, mbd, args); 32 if (logger.isDebugEnabled()) { 33 logger.debug("Finished creating instance of bean '" + beanName + "'"); 34 } 35 return beanInstance; 36 }</pre>

複製代碼

前面的代碼都沒什麼意義,代碼執行到第31行:

複製代碼

<pre> 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { 2 // Instantiate the bean.
3 BeanWrapper instanceWrapper = null;
4 if (mbd.isSingleton()) { 5 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
6 }
7 if (instanceWrapper == null) {
8 instanceWrapper = createBeanInstance(beanName, mbd, args); 9 } 10 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); 11 Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); 12
13 // Allow post-processors to modify the merged bean definition.
14 synchronized (mbd.postProcessingLock) { 15 if (!mbd.postProcessed) { 16 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 17 mbd.postProcessed = true; 18 } 19 } 20
21 // Eagerly cache singletons to be able to resolve circular references 22 // even when triggered by lifecycle interfaces like BeanFactoryAware.
23 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
24 isSingletonCurrentlyInCreation(beanName)); 25 if (earlySingletonExposure) { 26 if (logger.isDebugEnabled()) { 27 logger.debug("Eagerly caching bean '" + beanName +
28 "' to allow for resolving potential circular references"); 29 } 30 addSingletonFactory(beanName, new ObjectFactory() { 31 public Object getObject() throws BeansException { 32 return getEarlyBeanReference(beanName, mbd, bean); 33 } 34 }); 35 } 36
37 // Initialize the bean instance.
38 Object exposedObject = bean; 39 try { 40 populateBean(beanName, mbd, instanceWrapper); 41 if (exposedObject != null) { 42 exposedObject = initializeBean(beanName, exposedObject, mbd); 43 } 44 } 45 catch (Throwable ex) { 46 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 47 throw (BeanCreationException) ex; 48 } 49 else { 50 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); 51 } 52 } 53
54 if (earlySingletonExposure) { 55 Object earlySingletonReference = getSingleton(beanName, false); 56 if (earlySingletonReference != null) { 57 if (exposedObject == bean) { 58 exposedObject = earlySingletonReference; 59 } 60 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 61 String[] dependentBeans = getDependentBeans(beanName); 62 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); 63 for (String dependentBean : dependentBeans) { 64 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 65 actualDependentBeans.add(dependentBean); 66 } 67 } 68 if (!actualDependentBeans.isEmpty()) { 69 throw new BeanCurrentlyInCreationException(beanName, 70 "Bean with name '" + beanName + "' has been injected into other beans [" +
71 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
72 "] in its raw version as part of a circular reference, but has eventually been " +
73 "wrapped. This means that said other beans do not use the final version of the " +
74 "bean. This is often the result of over-eager type matching - consider using " +
75 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); 76 } 77 } 78 } 79 } 80
81 // Register bean as disposable.
82 try { 83 registerDisposableBeanIfNecessary(beanName, bean, mbd); 84 } 85 catch (BeanDefinitionValidationException ex) { 86 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); 87 } 88
89 return exposedObject; 90 }</pre>

複製代碼

doCreateBean方法

代碼跟蹤到這裏,已經到了主流程,接下來分段分析doCreateBean方法的代碼。

建立Bean實例

第8行的createBeanInstance方法,會建立出Bean的實例,幷包裝爲BeanWrapper,看一下createBeanInstance方法,只貼最後一段比較關鍵的:

複製代碼

<pre> 1 // Need to determine the constructor...
2 Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 3 if (ctors != null ||
4 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
5 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
6 return autowireConstructor(beanName, mbd, ctors, args); 7 }
8
9 // No special handling: simply use no-arg constructor.
10 return instantiateBean(beanName, mbd);</pre>

複製代碼

意思是bean標籤使用構造函數注入屬性的話,執行第6行,不然執行第10行。MultiFunctionBean使用默認構造函數,使用setter注入屬性,所以執行第10行代碼:

複製代碼

<pre> 1 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { 2 try { 3 Object beanInstance;
4 final BeanFactory parent = this;
5 if (System.getSecurityManager() != null) {
6 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
7 public Object run() { 8 return getInstantiationStrategy().instantiate(mbd, beanName, parent); 9 } 10 }, getAccessControlContext()); 11 } 12 else { 13 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 14 } 15 BeanWrapper bw = new BeanWrapperImpl(beanInstance); 16 initBeanWrapper(bw); 17 return bw; 18 } 19 catch (Throwable ex) { 20 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); 21 } 22 }</pre>

複製代碼

代碼執行到13行:

複製代碼

<pre> 1 public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { 2 // Don't override the class with CGLIB if no overrides.
3 if (beanDefinition.getMethodOverrides().isEmpty()) { 4 Constructor<?> constructorToUse; 5 synchronized (beanDefinition.constructorArgumentLock) { 6 constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
7 if (constructorToUse == null) {
8 final Class clazz = beanDefinition.getBeanClass(); 9 if (clazz.isInterface()) { 10 throw new BeanInstantiationException(clazz, "Specified class is an interface"); 11 } 12 try { 13 if (System.getSecurityManager() != null) { 14 constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() { 15 public Constructor run() throws Exception { 16 return clazz.getDeclaredConstructor((Class[]) null); 17 } 18 }); 19 } 20 else { 21 constructorToUse = clazz.getDeclaredConstructor((Class[]) null); 22 } 23 beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse; 24 } 25 catch (Exception ex) { 26 throw new BeanInstantiationException(clazz, "No default constructor found", ex); 27 } 28 } 29 } 30 return BeanUtils.instantiateClass(constructorToUse); 31 } 32 else { 33 // Must generate CGLIB subclass.
34 return instantiateWithMethodInjection(beanDefinition, beanName, owner); 35 } 36 }</pre>

複製代碼

整段代碼都在作一件事情,就是選擇一個使用的構造函數。固然第9行順帶作了一個判斷:實例化一個接口將報錯。

最後調用到30行,看一下代碼:

複製代碼

<pre> 1 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { 2 Assert.notNull(ctor, "Constructor must not be null");
3 try { 4 ReflectionUtils.makeAccessible(ctor);
5 return ctor.newInstance(args); 6 }
7 catch (InstantiationException ex) { 8 throw new BeanInstantiationException(ctor.getDeclaringClass(), 9 "Is it an abstract class?", ex); 10 } 11 catch (IllegalAccessException ex) { 12 throw new BeanInstantiationException(ctor.getDeclaringClass(), 13 "Is the constructor accessible?", ex); 14 } 15 catch (IllegalArgumentException ex) { 16 throw new BeanInstantiationException(ctor.getDeclaringClass(), 17 "Illegal arguments for constructor", ex); 18 } 19 catch (InvocationTargetException ex) { 20 throw new BeanInstantiationException(ctor.getDeclaringClass(), 21 "Constructor threw exception", ex.getTargetException()); 22 } 23 }</pre>

複製代碼

經過反射生成Bean的實例。看到前面有一步makeAccessible,這意味着即便Bean的構造函數是private、protected的,依然不影響Bean的構造。

最後注意一下,這裏被實例化出來的Bean並不會直接返回,而是會被包裝爲BeanWrapper繼續在後面使用。

doCreateBean方法

上文【Spring源碼分析】非懶加載的單例Bean初始化過程(上篇),分析了單例的Bean初始化流程,並跟蹤代碼進入了主流程,看到了Bean是如何被實例化出來的。先貼一下AbstractAutowireCapableBeanFactory的doCreateBean方法代碼:

複製代碼

<pre> 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { 2 // Instantiate the bean.
3 BeanWrapper instanceWrapper = null;
4 if (mbd.isSingleton()) { 5 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
6 }
7 if (instanceWrapper == null) {
8 instanceWrapper = createBeanInstance(beanName, mbd, args); 9 } 10 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); 11 Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); 12
13 // Allow post-processors to modify the merged bean definition.
14 synchronized (mbd.postProcessingLock) { 15 if (!mbd.postProcessed) { 16 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 17 mbd.postProcessed = true; 18 } 19 } 20
21 // Eagerly cache singletons to be able to resolve circular references 22 // even when triggered by lifecycle interfaces like BeanFactoryAware.
23 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
24 isSingletonCurrentlyInCreation(beanName)); 25 if (earlySingletonExposure) { 26 if (logger.isDebugEnabled()) { 27 logger.debug("Eagerly caching bean '" + beanName +
28 "' to allow for resolving potential circular references"); 29 } 30 addSingletonFactory(beanName, new ObjectFactory() { 31 public Object getObject() throws BeansException { 32 return getEarlyBeanReference(beanName, mbd, bean); 33 } 34 }); 35 } 36
37 // Initialize the bean instance.
38 Object exposedObject = bean; 39 try { 40 populateBean(beanName, mbd, instanceWrapper); 41 if (exposedObject != null) { 42 exposedObject = initializeBean(beanName, exposedObject, mbd); 43 } 44 } 45 catch (Throwable ex) { 46 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 47 throw (BeanCreationException) ex; 48 } 49 else { 50 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); 51 } 52 } 53
54 if (earlySingletonExposure) { 55 Object earlySingletonReference = getSingleton(beanName, false); 56 if (earlySingletonReference != null) { 57 if (exposedObject == bean) { 58 exposedObject = earlySingletonReference; 59 } 60 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 61 String[] dependentBeans = getDependentBeans(beanName); 62 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); 63 for (String dependentBean : dependentBeans) { 64 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 65 actualDependentBeans.add(dependentBean); 66 } 67 } 68 if (!actualDependentBeans.isEmpty()) { 69 throw new BeanCurrentlyInCreationException(beanName, 70 "Bean with name '" + beanName + "' has been injected into other beans [" +
71 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
72 "] in its raw version as part of a circular reference, but has eventually been " +
73 "wrapped. This means that said other beans do not use the final version of the " +
74 "bean. This is often the result of over-eager type matching - consider using " +
75 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); 76 } 77 } 78 } 79 } 80
81 // Register bean as disposable.
82 try { 83 registerDisposableBeanIfNecessary(beanName, bean, mbd); 84 } 85 catch (BeanDefinitionValidationException ex) { 86 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); 87 } 88
89 return exposedObject; 90 }</pre>

複製代碼

下面繼續分析初始化一個Bean的流程,不過重要的流程就跳過了。

屬性注入

屬性注入的代碼比較好找,能夠看一下40行,取名爲populateBean,即填充Bean的意思,看一下代碼實現:

複製代碼

<pre> 1 protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { 2 PropertyValues pvs = mbd.getPropertyValues(); 3
4 if (bw == null) {
5 if (!pvs.isEmpty()) {
6 throw new BeanCreationException( 7 mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
8 }
9 else { 10 // Skip property population phase for null instance.
11 return; 12 } 13 } 14
15 // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the 16 // state of the bean before properties are set. This can be used, for example, 17 // to support styles of field injection.
18 boolean continueWithPropertyPopulation = true; 19
20 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 21 for (BeanPostProcessor bp : getBeanPostProcessors()) { 22 if (bp instanceof InstantiationAwareBeanPostProcessor) { 23 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 24 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { 25 continueWithPropertyPopulation = false; 26 break; 27 } 28 } 29 } 30 } 31
32 if (!continueWithPropertyPopulation) { 33 return; 34 } 35
36 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
37 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 38 MutablePropertyValues newPvs = new MutablePropertyValues(pvs); 39
40 // Add property values based on autowire by name if applicable.
41 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { 42 autowireByName(beanName, mbd, bw, newPvs); 43 } 44
45 // Add property values based on autowire by type if applicable.
46 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 47 autowireByType(beanName, mbd, bw, newPvs); 48 } 49
50 pvs = newPvs; 51 } 52
53 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 54 boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); 55
56 if (hasInstAwareBpps || needsDepCheck) { 57 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); 58 if (hasInstAwareBpps) { 59 for (BeanPostProcessor bp : getBeanPostProcessors()) { 60 if (bp instanceof InstantiationAwareBeanPostProcessor) { 61 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 62 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 63 if (pvs == null) { 64 return; 65 } 66 } 67 } 68 } 69 if (needsDepCheck) { 70 checkDependencies(beanName, mbd, filteredPds, pvs); 71 } 72 } 73
74 applyPropertyValues(beanName, mbd, bw, pvs); 75 }</pre>

複製代碼

這段代碼層次有點深,跟一下74行的applyPropertyValues方法,最後那個pvs的實現類爲MutablePropertyValues,裏面持有一個List<PropertyValue>,每個PropertyValue包含了此Bean屬性的屬性名與屬性值。74行的代碼實現爲:

複製代碼

<pre> 1 protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { 2 if (pvs == null || pvs.isEmpty()) { 3 return;
4 }
5
6 MutablePropertyValues mpvs = null;
7 List<PropertyValue> original; 8
9 if (System.getSecurityManager()!= null) { 10 if (bw instanceof BeanWrapperImpl) { 11 ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); 12 } 13 } 14
15 if (pvs instanceof MutablePropertyValues) { 16 mpvs = (MutablePropertyValues) pvs; 17 if (mpvs.isConverted()) { 18 // Shortcut: use the pre-converted values as-is.
19 try { 20 bw.setPropertyValues(mpvs); 21 return; 22 } 23 catch (BeansException ex) { 24 throw new BeanCreationException( 25 mbd.getResourceDescription(), beanName, "Error setting property values", ex); 26 } 27 } 28 original = mpvs.getPropertyValueList(); 29 } 30 else { 31 original = Arrays.asList(pvs.getPropertyValues()); 32 } 33
34 TypeConverter converter = getCustomTypeConverter(); 35 if (converter == null) { 36 converter = bw; 37 } 38 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); 39
40 // Create a deep copy, resolving any references for values.
41 List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size()); 42 boolean resolveNecessary = false; 43 for (PropertyValue pv : original) { 44 if (pv.isConverted()) { 45 deepCopy.add(pv); 46 } 47 else { 48 String propertyName = pv.getName(); 49 Object originalValue = pv.getValue(); 50 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); 51 Object convertedValue = resolvedValue; 52 boolean convertible = bw.isWritableProperty(propertyName) &&
53 !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); 54 if (convertible) { 55 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); 56 } 57 // Possibly store converted value in merged bean definition, 58 // in order to avoid re-conversion for every created bean instance.
59 if (resolvedValue == originalValue) { 60 if (convertible) { 61 pv.setConvertedValue(convertedValue); 62 } 63 deepCopy.add(pv); 64 } 65 else if (convertible && originalValue instanceof TypedStringValue &&
66 !((TypedStringValue) originalValue).isDynamic() &&
67 !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { 68 pv.setConvertedValue(convertedValue); 69 deepCopy.add(pv); 70 } 71 else { 72 resolveNecessary = true; 73 deepCopy.add(new PropertyValue(pv, convertedValue)); 74 } 75 } 76 } 77 if (mpvs != null && !resolveNecessary) { 78 mpvs.setConverted(); 79 } 80
81 // Set our (possibly massaged) deep copy.
82 try { 83 bw.setPropertyValues(new MutablePropertyValues(deepCopy)); 84 } 85 catch (BeansException ex) { 86 throw new BeanCreationException( 87 mbd.getResourceDescription(), beanName, "Error setting property values", ex); 88 } 89 }</pre>

複製代碼

以後在第41行~第76行作了一次深拷貝(只是名字叫作深拷貝而已,其實就是遍歷PropertyValue而後一個一個賦值到一個新的List而不是Java語義上的Clone,這裏使用深拷貝是爲了解析Values值中的全部引用),將PropertyValue一個一個賦值到一個新的List裏面去,起名爲deepCopy。最後執行83行進行復制,bw即BeanWrapper,持有Bean實例的一個Bean包裝類,看一下代碼實現:

複製代碼

<pre> 1 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) 2 throws BeansException { 3
4 List<PropertyAccessException> propertyAccessExceptions = null;
5 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
6 ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
7 for (PropertyValue pv : propertyValues) { 8 try { 9 // This method may throw any BeansException, which won't be caught 10 // here, if there is a critical failure such as no matching field. 11 // We can attempt to deal only with less serious exceptions.
12 setPropertyValue(pv); 13 } 14 catch (NotWritablePropertyException ex) { 15 if (!ignoreUnknown) { 16 throw ex; 17 } 18 // Otherwise, just ignore it and continue...
19 } 20 catch (NullValueInNestedPathException ex) { 21 if (!ignoreInvalid) { 22 throw ex; 23 } 24 // Otherwise, just ignore it and continue...
25 } 26 catch (PropertyAccessException ex) { 27 if (propertyAccessExceptions == null) { 28 propertyAccessExceptions = new LinkedList<PropertyAccessException>(); 29 } 30 propertyAccessExceptions.add(ex); 31 } 32 } 33
34 // If we encountered individual exceptions, throw the composite exception.
35 if (propertyAccessExceptions != null) { 36 PropertyAccessException[] paeArray =
37 propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]); 38 throw new PropertyBatchUpdateException(paeArray); 39 } 40 }</pre>

複製代碼

這段代碼沒什麼特別的,遍歷前面的deepCopy,拿每個PropertyValue,執行第12行的setPropertyValue:

複製代碼

<pre> 1 public void setPropertyValue(PropertyValue pv) throws BeansException { 2 PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens; 3 if (tokens == null) {
4 String propertyName = pv.getName(); 5 BeanWrapperImpl nestedBw;
6 try { 7 nestedBw = getBeanWrapperForPropertyPath(propertyName); 8 }
9 catch (NotReadablePropertyException ex) { 10 throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, 11 "Nested property in path '" + propertyName + "' does not exist", ex); 12 } 13 tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName)); 14 if (nestedBw == this) { 15 pv.getOriginalPropertyValue().resolvedTokens = tokens; 16 } 17 nestedBw.setPropertyValue(tokens, pv); 18 } 19 else { 20 setPropertyValue(tokens, pv); 21 } 22 }</pre>

複製代碼

找一個合適的BeanWrapper,這裏就是自身,而後執行17行的setPropertyValue方法進入最後一步,方法很是長,截取核心的一段:

複製代碼

<pre> 1 final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
2 ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
3 pd.getWriteMethod());
4 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
5 if (System.getSecurityManager()!= null) {
6 AccessController.doPrivileged(new PrivilegedAction<Object>() {
7 public Object run() { 8 writeMethod.setAccessible(true);
9 return null; 10 } 11 }); 12 } 13 else { 14 writeMethod.setAccessible(true); 15 } 16 } 17 final Object value = valueToApply; 18 if (System.getSecurityManager() != null) { 19 try { 20 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { 21 public Object run() throws Exception { 22 writeMethod.invoke(object, value); 23 return null; 24 } 25 }, acc); 26 } 27 catch (PrivilegedActionException ex) { 28 throw ex.getException(); 29 } 30 } 31 else { 32 writeMethod.invoke(this.object, value); 33 } </pre>

複製代碼

大體流程就是兩步:

(1)拿到寫方法並將方法的可見性設置爲true

(2)拿到Value值,對Bean經過反射調用寫方法

這樣完成了對於Bean屬性值的設置。

Aware注入

接下來是Aware注入。在使用Spring的時候咱們將本身的Bean實現BeanNameAware接口、BeanFactoryAware接口等,依賴容器幫咱們注入當前Bean的名稱或者Bean工廠,其代碼實現先追溯到上面doCreateBean方法的42行initializeBean方法:

複製代碼

<pre> 1 protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { 2 if (System.getSecurityManager() != null) {
3 AccessController.doPrivileged(new PrivilegedAction<Object>() {
4 public Object run() { 5 invokeAwareMethods(beanName, bean);
6 return null;
7 }
8 }, getAccessControlContext());
9 } 10 else { 11 invokeAwareMethods(beanName, bean); 12 } 13
14 Object wrappedBean = bean; 15 if (mbd == null || !mbd.isSynthetic()) { 16 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 17 } 18
19 try { 20 invokeInitMethods(beanName, wrappedBean, mbd); 21 } 22 catch (Throwable ex) { 23 throw new BeanCreationException( 24 (mbd != null ? mbd.getResourceDescription() : null), 25 beanName, "Invocation of init method failed", ex); 26 } 27
28 if (mbd == null || !mbd.isSynthetic()) { 29 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 30 } 31 return wrappedBean; 32 }</pre>

複製代碼

看一下上面第5行的實現:

複製代碼

<pre> 1 private void invokeAwareMethods(final String beanName, final Object bean) { 2 if (bean instanceof BeanNameAware) { 3 ((BeanNameAware) bean).setBeanName(beanName);
4 }
5 if (bean instanceof BeanClassLoaderAware) { 6 ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
7 }
8 if (bean instanceof BeanFactoryAware) { 9 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); 10 } 11 }</pre>

複製代碼

看到這裏判斷,若是bean是BeanNameAware接口的實現類會調用setBeanName方法、若是bean是BeanClassLoaderAware接口的實現類會調用setBeanClassLoader方法、若是是BeanFactoryAware接口的實現類會調用setBeanFactory方法,注入對應的屬性值。

調用BeanPostProcessor的postProcessBeforeInitialization方法

上面initializeBean方法再看16行其實現:

複製代碼

<pre> 1 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) 2 throws BeansException { 3
4 Object result = existingBean; 5 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { 6 result = beanProcessor.postProcessBeforeInitialization(result, beanName); 7 if (result == null) {
8 return result; 9 } 10 } 11 return result; 12 }</pre>

複製代碼

遍歷每一個BeanPostProcessor接口實現,調用postProcessBeforeInitialization方法,這個接口的調用時機以後會總結,這裏就代碼先簡單提一下。

調用初始化方法

initializeBean方法的20行,調用Bean的初始化方法,看一下實現:

複製代碼

<pre> 1 protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) 2 throws Throwable { 3
4 boolean isInitializingBean = (bean instanceof InitializingBean); 5 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
6 if (logger.isDebugEnabled()) { 7 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
8 }
9 if (System.getSecurityManager() != null) { 10 try { 11 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { 12 public Object run() throws Exception { 13 ((InitializingBean) bean).afterPropertiesSet(); 14 return null; 15 } 16 }, getAccessControlContext()); 17 } 18 catch (PrivilegedActionException pae) { 19 throw pae.getException(); 20 } 21 } 22 else { 23 ((InitializingBean) bean).afterPropertiesSet(); 24 } 25 } 26
27 if (mbd != null) { 28 String initMethodName = mbd.getInitMethodName(); 29 if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
30 !mbd.isExternallyManagedInitMethod(initMethodName)) { 31 invokeCustomInitMethod(beanName, bean, mbd); 32 } 33 } 34 }</pre>

複製代碼

看到,代碼作了兩件事情:

一、先判斷Bean是否InitializingBean的實現類,是的話,將Bean強轉爲InitializingBean,直接調用afterPropertiesSet()方法

二、嘗試去拿init-method,假若有的話,經過反射,調用initMethod

所以,兩種方法各有優劣:使用實現InitializingBean接口的方式效率更高一點,由於init-method方法是經過反射進行調用的;從另一個角度講,使用init-method方法以後和Spring的耦合度會更低一點。具體使用哪一種方式調用初始化方法,看我的喜愛。

調用BeanPostProcessor的postProcessAfterInitialization方法

最後一步,initializeBean方法的29行:

複製代碼

<pre> 1 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 2 throws BeansException { 3
4 Object result = existingBean; 5 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { 6 result = beanProcessor.postProcessAfterInitialization(result, beanName); 7 if (result == null) {
8 return result; 9 } 10 } 11 return result; 12 }</pre>

複製代碼

一樣遍歷BeanPostProcessor,調用postProcessAfterInitialization方法。所以對於BeanPostProcessor方法總結一下:

一、在初始化每個Bean的時候都會調用每個配置的BeanPostProcessor的方法

二、在Bean屬性設置、Aware設置後調用postProcessBeforeInitialization方法

三、在初始化方法調用後調用postProcessAfterInitialization方法

註冊須要執行銷燬方法的Bean

接下來看一下最上面doCreateBean方法的第83行registerDisposableBeanIfNecessary(beanName, bean, mbd)這一句,完成了建立Bean的最後一件事情:註冊須要執行銷燬方法的Bean。

看一下方法的實現:

複製代碼

<pre> 1 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { 2 AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
3 if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { 4 if (mbd.isSingleton()) { 5 // Register a DisposableBean implementation that performs all destruction 6 // work for the given bean: DestructionAwareBeanPostProcessors, 7 // DisposableBean interface, custom destroy method.
8 registerDisposableBean(beanName,
9 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 10 } 11 else { 12 // A bean with a custom scope...
13 Scope scope = this.scopes.get(mbd.getScope()); 14 if (scope == null) { 15 throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'"); 16 } 17 scope.registerDestructionCallback(beanName, 18 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 19 } 20 } 21 }</pre>

複製代碼

其中第3行第一個判斷爲必須不是prototype(原型)的,第二個判斷requiresDestruction方法的實現爲:

<pre>1 protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) { 2 return (bean != null &&
3 (bean instanceof DisposableBean || mbd.getDestroyMethodName() != null ||
4 hasDestructionAwareBeanPostProcessors())); 5 }</pre>

要註冊銷燬方法,Bean須要至少知足如下三個條件之一:

(1)Bean是DisposableBean的實現類,此時執行DisposableBean的接口方法destroy()

(2)Bean標籤中有配置destroy-method屬性,此時執行destroy-method配置指定的方法

(3)當前Bean對應的BeanFactory中持有DestructionAwareBeanPostProcessor接口的實現類,此時執行DestructionAwareBeanPostProcessor的接口方法postProcessBeforeDestruction

在知足上面三個條件之一的狀況下,容器便會註冊銷燬該Bean,註冊Bean的方法很簡單,見registerDisposableBean方法實現:

<pre>1 public void registerDisposableBean(String beanName, DisposableBean bean) { 2 synchronized (this.disposableBeans) { 3 this.disposableBeans.put(beanName, bean); 4 } 5 }</pre>

容器銷燬的時候,會遍歷disposableBeans,逐一執行銷燬方法。

流程總結

本文和上篇文章分析了Spring Bean初始化的步驟,最後用一幅圖總結一下Spring Bean初始化的流程:

圖只是起梳理流程做用,拋磚引玉,具體代碼實現還須要網友朋友們照着代碼本身去一步一步分析。

圖片描述

微信公衆號【黃小斜】做者是螞蟻金服 JAVA 工程師,專一於 JAVA 後端技術棧:SpringBoot、SSM全家桶、MySQL、分佈式、中間件、微服務,同時也懂點投資理財,堅持學習和寫做,相信終身學習的力量!關注公衆號後回覆」架構師「便可領取 Java基礎、進階、項目和架構師等免費學習資料,更有數據庫、分佈式、微服務等熱門技術學習視頻,內容豐富,兼顧原理和實踐,另外也將贈送做者原創的Java學習指南、Java程序員面試指南等乾貨資源
相關文章
相關標籤/搜索