本文是筆者所著的 Spring Core Container 源碼分析系列之一;java
本篇文章主要試圖梳理出 Spring Beans 的初始化主流程
和相關核心代碼邏輯;spring
本文轉載自本人的私人博客,傷神的博客: http://www.shangyang.me/2017/...緩存
本文爲做者的原創做品,轉載需註明出處;架構
參考 Spring Core Container 源碼分析二:環境準備app
依然使用這個官網上的用例,來進行調試;ide
Person.java函數
package org.shangyang.spring.container; /** - - @author shangyang * */ public class Person { String name; Person spouse; public String getName() { return name; } public void setName(String name) { this.name = name; } public Person getSpouse() { return spouse; } public void setSpouse(Person spouse) { this.spouse = spouse; } }
beans.xml源碼分析
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 傳統的方式 --> <bean name="john" class="org.shangyang.spring.container.Person"> <property name="name" value="John Doe"/> <property name="spouse" ref="jane"/> </bean> <bean name="jane" class="org.shangyang.spring.container.Person"> <property name="name" value="Jane Doe"/> </bean> </beans>
@Test public void testApplicationContext(){ @SuppressWarnings("resource") ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Person p = context.getBean("john", Person.class); assertEquals("John Doe", p.getName() ); assertEquals("Jane Doe", p.getSpouse().getName() ); }
備註,這裏只針對 Spring 容器實例化 singleton bean 的主流程進行介紹;_singleton_ bean 在 Spring 容器中被初始化的特色是,在 Spring 容器的啓動過程當中就進行初始化;post
(最好的分析源碼的方式,就是經過高屋建瓴,逐個擊破的方式;首先經過流程圖得到它的藍圖(頂層設計圖),而後再根據藍圖上的點逐個擊破;最後才能達到融會貫通,成竹在胸的境界;因此,這裏做者用這樣的方式帶你深刻剖析 Spring 容器裏面的核心點,以及相關主流程究竟是如何運做的。)測試
本章節咱們將詳細去闡述的是,Spring 容器是如何對 Singleton bean 進行初始化並註冊到當前容器的;與之相關的主要有兩個流程,
AbstractBeanFactory#getBean(beanFactory)
方法進行構造;更詳細的介紹參考 Do Get Bean 流程。該部分參考新的博文 Spring Core Container 源碼分析七:註冊 Bean Definitions
Do Get Bean 流程的入口是 AbstractBeanFactory#doGetBean 方法,主流程圖以下,
主流程大體爲,從緩存中找到是否已經實例化了該 singleton bean,若是已經實例化好了,那麼就直接返回;若是在緩存中沒有找到,則將當前的 bean 封裝爲 RootBeanDefinition,而後經過調用 DefaultSingletonBeanRegistry#getSingleton 獲得初始化好的 singleton bean,而後將其註冊至緩存( step 1.3.3 addSingleton ),而後再判斷是普通 bean 仍是 factory bean 做必要的處理( step 1.4 getObjectForBeanInstance )後,最後返回;
初始化了一個 RootBeanDefinition
對象,正如其類名描述的那樣,是該 bean 的頂層描述;包含了 bean 的字段屬性,ref屬性以及繼承相關等等屬性;
此步驟的相關代碼以下,
// Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { 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); }
調用父類 DefaultSingletonBeanRegistry#getSingleton 方法;注意,這裏經過接口 ObjectFactory<Object>
定義了一個回調方法 _getObject()_,經過該回調方法調用 AbstractAutowireCapableBeanFactory#createBean 方法,經過此回調方法正式拉開了實例化 bean 的序幕
。
AbstractAutowireCapableBeanFactory#doCreateBean 方法是初始化 bean 的最核心的入口方法,執行流程如 Do Get Bean 流程所示,
下面咱們分別來分析這三件事情
該步驟對應 Do Get Bean 流程中的 _Step 1.3.1.1.3.1 createBeanInstance_;根據 bean 的不一樣配置方式,實現了三種實例化 bean 的方式,分別是 factory instantiate bean、autwire instantiate bean 以及 default instantiate bean;
用工廠方法實例化 bean,待敘;
經過 autowire 註解的方式實例化 bean,待敘;
此步驟對應 Do Get Bean 流程中的 Step 1.3.1.1.3.1.3 instantiateBean_,其對應子流程 _default instantiate bean 以下圖所示,
注意幾點
Java 反射
實例化了 bean,並沒有對其進行任何的參數賦值,賦值過程參考 populate bean 流程;將 bean 封裝爲 BeanWrapper,而後
最後返回 BeanWrapper
對應 Do Get Bean 流程中的 Step 1.3.1.1.3.4 populateBean_,經過調用 _AbstractAutowireCapableBeanFactory#populateBean 正式給 bean 的參數進行賦值;爲何方法名取名爲populate
呢?查百度翻譯,結果是居住於、生活於、移民於、落戶於的意思,絲毫沒有賦值的意思,可是記得之前和美國人共事的時候,他們很是喜歡用這個詞populate
,特別是在建立某個對象的時候,他們特別喜歡用這個詞;後來無心中發現,populate
有建立
和填充
的意思,因此,這裏的意思就是,填充
這個 bean;下面看看 populate bean 的流程圖,看看它是怎麼玩的,
經過調用 AbstractAutowireCapableBeanFactory#applyPropertyValues 方法正式給 bean 進行賦值操做,賦值的主流程主要包括兩個部分,resolve property value object 和 set property value to bean
對應上面 Sequence Diagram 中的 Step 1.5 - Step 1.7_;這一步主要是去遍歷當前 bean 全部的 property,並依次解析(resolve)獲得對應的 Java 對象;經過方法 _BeanDefinitionValueResolver#resolveValueIfNecessary 進行解析,解析的過程是針對不一樣類型的 Property,採用不一樣的解析方式,裏面目前總共對應了十種類型,先看看它的源碼,
public Object resolveValueIfNecessary(Object argName, Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. if (value instanceof RuntimeBeanReference) { // 這裏表示該 bean definition ref 引用的是一個 bean,那麼這裏,必須對該 bean 進行初始化操做; RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } else if (value instanceof RuntimeBeanNameReference) { String refName = ((RuntimeBeanNameReference) value).getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (!this.beanFactory.containsBean(refName)) { throw new BeanDefinitionStoreException( "Invalid bean name '" + refName + "' in bean reference for " + argName); } return refName; } else if (value instanceof BeanDefinitionHolder) { // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases. BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value; return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition()); } else if (value instanceof BeanDefinition) { // Resolve plain BeanDefinition, without contained name: use dummy name. BeanDefinition bd = (BeanDefinition) value; String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(bd); return resolveInnerBean(argName, innerBeanName, bd); } else if (value instanceof ManagedArray) { // May need to resolve contained runtime references. ManagedArray array = (ManagedArray) value; Class<?> elementType = array.resolvedElementType; if (elementType == null) { String elementTypeName = array.getElementTypeName(); if (StringUtils.hasText(elementTypeName)) { try { elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader()); array.resolvedElementType = elementType; } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, ex); } } else { elementType = Object.class; } } return resolveManagedArray(argName, (List<?>) value, elementType); } else if (value instanceof ManagedList) { // May need to resolve contained runtime references. return resolveManagedList(argName, (List<?>) value); } else if (value instanceof ManagedSet) { // May need to resolve contained runtime references. return resolveManagedSet(argName, (Set<?>) value); } else if (value instanceof ManagedMap) { // May need to resolve contained runtime references. return resolveManagedMap(argName, (Map<?, ?>) value); } else if (value instanceof ManagedProperties) { Properties original = (Properties) value; Properties copy = new Properties(); for (Map.Entry<Object, Object> propEntry : original.entrySet()) { Object propKey = propEntry.getKey(); Object propValue = propEntry.getValue(); if (propKey instanceof TypedStringValue) { propKey = evaluate((TypedStringValue) propKey); } if (propValue instanceof TypedStringValue) { propValue = evaluate((TypedStringValue) propValue); } copy.put(propKey, propValue); } return copy; } else if (value instanceof TypedStringValue) { // Convert value to target type here. TypedStringValue typedStringValue = (TypedStringValue) value; Object valueObject = evaluate(typedStringValue); try { Class<?> resolvedTargetType = resolveTargetType(typedStringValue); if (resolvedTargetType != null) { return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType); } else { return valueObject; } } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, ex); } } else { return evaluate(value); } }
這裏主要關注兩類解析,
對應須要被解析的配置爲john
的 property spouse
,它所對應的值是另外一個 bean jane
;既是一個去解析一個ref bean
。
<property name="spouse" ref="jane"/>
因此能夠看到,源碼中是經過 resolveReference 方法調用 AbstractBeanFactory#getBean 方法去實例化
一個 bean jane
並返回;對應的源碼以下,
BeanDefinitionValueResolver#resolveReference
/** * Resolve a reference to another bean in the factory. */ private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { String refName = ref.getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (ref.isToParent()) { if (this.beanFactory.getParentBeanFactory() == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available"); } return this.beanFactory.getParentBeanFactory().getBean(refName); } else { Object bean = this.beanFactory.getBean(refName); // 去獲得這個 ref bean this.beanFactory.registerDependentBean(refName, this.beanName); // 註冊 return bean; } } catch (BeansException ex) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex); } }
經過調用this.beanFactory.getBean(refName)
再次進入Do Get Bean 流程初始化獲得該 _ref bean_;
最後,將解析出來的 Property value 放在一個deepCopy
的 ArrayList 列表對象中;顧名思義,就是對值進行了一次深度的拷貝,而後將其做爲 bean 的參數,隨後開始進行賦值操做);
這裏主要被解析的 Property value 的類型配置爲
<property name="name" value="John Doe"/>
其 Property value 的值在配置文件中就是一個純的字符串類型;但從源碼中能夠知道,Property value 是能夠包含 value type 的,因此,在解析 TypedStringValue 的時候,須要根據 value type 進行解析;具體邏輯參考resolveTargetType(typedStringValue);
方法。
此步驟的主流程主要是經過Java Method 反射
將解析出來的值賦值給當前的 bean;對應時序圖中的 Step 1.8 setPropertyValues
能夠看到,經過遍歷 deepCopy
ArrayList 對象中已經解析事後的 PropertyValue,最終由 BeanWrapperImpl 對象經過方法的反射,將值注入給當前的 bean,_Step 1.8.1.2.1.2.2 writeMethod.invoke_
BeanWrapperImpl.java 省略了大部分可有可無的代碼,
@Override public void setValue(final Object object, Object valueToApply) throws Exception{ final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() : this.pd.getWriteMethod()); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { writeMethod.setAccessible(true); return null; } }); } else { writeMethod.setAccessible(true); } } .... writeMethod.invoke(getWrappedInstance(), valueToApply); .... }
經過這一步,將相關的 property populate 給 bean 之後,纔算 bean 的實例化完成;
正如流程圖中所描述的那樣,這個步驟的名字很是然人迷惑,我將流程圖中寫的備註摘錄以下,
"注意, 這裏的名稱很容易讓人產生混淆, 很容易讓人產生這樣一個疑問, 前面不是已經初始化好了, bean 建立好了, bean 相關的 property 也設置好了, 怎麼這裏還要進行初始化? 這裏其實偏偏充分體現了西方人寫代碼的嚴謹, 前面的部分叫作 instantiation, 叫作"實例化", 而這裏叫作 initialization, 叫作 "初始化"; 這樣一說, 差很少就明白了, "實例化"就是從 class 獲得 instance 的過程; 而"初始化", 包含的意義更普遍, 其意義包含了"實例化"和其它對 instance 的修飾的過程, 而這裏, 其實就是對已經建立好的 bean instance 進行"修飾"的過程。"
因此,這裏的 initialize 其實就是對經過 instantiate bean 和 populate bean 兩個步驟實例化好的 bean 進行後續必要的修飾;咱們經過流程圖來看看,它是怎麼去修飾的,
經過 AbstractAutowireCapableBeanFactory#initializeBean 方法進行對 bean 的修飾過程,看源碼,(刪除了大部分不相關的代碼)
AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { invokeAwareMethods(beanName, bean); // 調用實現了 *Aware 接口的方法,好比注入 ApplicationContext... Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 調用 bean-post-processor 的 before initialization 回調方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); // 調用 InitializingBean#afterPropertiesSet 回調 } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 調用 bean-post-processor 的 after initialization 回調方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; // 這裏的 wrapped bean 指的是被 bean-post-processor 修飾之後的包裝 bean }
整個過程能夠理解爲三大塊,
下面,咱們依次來梳理這三個部分;
對應流程圖中的 _Step 1.1 invokeAwareMethods_,該步驟註冊全部實現了Aware
接口的 beans
Aware.java
/** * Marker superinterface indicating that a bean is eligible to be * notified by the Spring container of a particular framework object * through a callback-style method. Actual method signature is * determined by individual subinterfaces, but should typically * consist of just one void-returning method that accepts a single * argument. * * <p>Note that merely implementing {@link Aware} provides no default * functionality. Rather, processing must be done explicitly, for example * in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}. * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor} * and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory} * for examples of processing {@code *Aware} interface callbacks. * * @author Chris Beams * @since 3.1 */ public interface Aware { }
從 Aware 接口的註釋中能夠看到,容許實現了該 Aware 接口的當前 bean 可以有機會經過回調的方式注入 Spring 容器中默認實現了 Aware 接口的 bean,好比 BeanFactory 等;看看源碼,
AbstractAutowireCapableBeanFactory.java
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) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
能夠看到,注入了三種狀況,
當梳理完這個部分之後,我相信讀者會和我同樣有這樣的疑問,咱們不是常常經過Aware
的方式注入ApplicaitonContext
對象的嗎?但和明顯,上述的代碼並無注入ApplicationContext
對象呀?看以下部分分析,
下列部分是延生部分
可是要特別特別注意的是,這裏並沒有注入ApplicationContext
對象,要注入ApplicaitonContext
對象,bean 必須實現ApplicatonContextAware
接口;
ApplicationContextAware.java
public interface ApplicationContextAware extends Aware { /** * Set the ApplicationContext that this object runs in. * Normally this call will be used to initialize the object. * <p>Invoked after population of normal bean properties but before an init callback such * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()} * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader}, * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and * {@link MessageSourceAware}, if applicable. * @param applicationContext the ApplicationContext object to be used by this object * @throws ApplicationContextException in case of context initialization errors * @throws BeansException if thrown by application context methods * @see org.springframework.beans.factory.BeanInitializationException */ void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }
從註解中能夠看到,它明確標註,是在 populate bean 之後,在 處理 InitializingBean 接口回調 以前調用,那是究竟是在什麼時刻呢?咱們查看下方法 setApplicationContext 方法在 workspace 中的引用,它是在 ApplicationContextAwareProcessor#invokeAwareInterfaces 方法中被調用,而 ApplicationContextAwareProcessor 正好是一個 BeanPostProcessor 對象,因此,ApplicaitonContext
對象其實是在 bean-post-procesor before initialization流程中被注入的,看源碼,
ApplicationContextAwareProcessor.java (省略了大部分不相關的代碼)
class ApplicationContextAwareProcessor implements BeanPostProcessor { private final ConfigurableApplicationContext applicationContext; private final StringValueResolver embeddedValueResolver; /** * Create a new ApplicationContextAwareProcessor for the given context. */ public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory()); } @Override public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; .... invokeAwareInterfaces(bean); .... return bean; } private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } }
先來看看BeanPostProcessor
接口的源碼,
public interface BeanPostProcessor { /** * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /** * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. * <p>This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
該接口定義了兩個回調方法,
因此,bean-post-processors 總共有兩次調用的時機,分別是 before initialization 和 after initialization,並且要特別注意的是,該回調方法是針對對容器中全部的
普通 bean 進行的回調;
該步驟對應 Step 1.2 applyBeanPostProcessorsBeforeInitialization_,而後正式調用 _Step 1.2.1 beanPostProcessor.postProcessBeforeInitialization bean-post-processor 的回調方法,不過這裏要注意的是,若是 Step 1.2.1 返回 null,會終止餘下的 post-bean-processor 的執行,而且直接返回一個 null,該 null 一樣被視爲是封裝後的產物,既然是 null,那麼後續的 bean-post-processor 也無需處理了,也沒法對原有的 bean 進行包裝了.. 不過,我到以爲這裏的 Spring 源碼的邏輯應該改進一下
,不容許返回 null 的狀況,若是返回 null 則報錯最好,由於 bean-post-processor 是對原有 bean 進行修飾,是新增屬性,而非幹掉實例自己.. 來看看源碼,
AbstractAutowireCapableBeanFactory.java
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
若是某個 beanProcessor 處理返回一個 null 則直接返回,而且終止其他的 bean-post-processors
對應的是 step 1.4 applyBeanPostProcessorsAfterInitialization 步驟,裏面的邏輯和 before initialization 邏輯相似,再也不贅述。
該步驟對應的是 _Step 1.3: invokeInitMethod_,回調 InitializingBean 接口方法,看源碼,
AbstractAutowireCapableBeanFactory.java (刪除了大部分不相關的代碼)
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } ..... ((InitializingBean) bean).afterPropertiesSet(); ..... } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
能夠看到,主要回調的是InitializingBean
接口的afterPropertiesSet
方法,因此,咱們可讓某個 bean 實現 InitializingBean 接口,並經過該接口實現一些當 bean 實例化好之後的回調方法,注意afterPropertiesSet
並不返回任何值,因此,這裏不是像 bean-post-processor 那樣對 bean 起到修飾的做用,而是起到純粹的調用做用;
以上即是 Spring IoC 容器的核心實現了,容器要達到的最本質的目的就是IoC
既反轉控制
,由容器來負責管理對象實例相關依賴的初始化和注入,而再也不是由 bean 本身去控制本身的依賴的初始化和注入過程了;而IoC
的實現是經過DI
既是依賴注入實現的;也就是爲何上面所介紹的內容都是圍繞着 Spring 容器如何實例化一個 bean,如何賦值,如何進行回調等一系列在 bean 的構建聲明週期過程當中的種種行爲;
這樣作能達到的好處就是,
(這裏我忽然想到「微內核架構」,Java 的一種內置的依賴注入的方式,經過在 META-INF 中配置接口屬性文件,裏面其實就是配置的一個接口的實現類,經過它來控制接口在 JVM 中該接口所使用的實現類;但它只是控制某個接口如何在 JVM 中實現,將接口的實現翻轉控制了,而 Spring 是對全部的 Class Instance 進行翻轉控制,因此一個是站在局部上的反轉控制設計,一個是站在全局上的反轉控制設計,不可同日而語!)