超詳細解析Spring Bean的創(chuàng)建過程
Spring Bean 的生命周期
BeanFactory 創(chuàng)建對象
在 BeanFactory 接口中定義了獲取 Bean 實例的方法 getBean。
@Test public void testDefaultListableBeanFactory() { // 創(chuàng)建工廠 DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); // 創(chuàng)建 XML 閱讀器,并指定關(guān)聯(lián)的工廠 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); // 開始解析加載 Bean reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml")); System.out.println(factory.getBean("user")); }
Spring 工廠創(chuàng)建對象的過程其實就是 factory.getBean("user")
對應(yīng)的實現(xiàn),這個創(chuàng)建邏輯可以說是 Spring 中最復(fù)雜的地方,其中會完整的體現(xiàn)上面生命周期的各個步驟,以及對單例對象、多實例對象的處理,接下來我們將深入源碼,解析整個對象的創(chuàng)建過程。
Bean 創(chuàng)建過程
獲取 Bean 的方法是 getBean,其來自 DefaultListableBeanFactory 的父類 AbstractAutowireCapableBeanFactory 的父類 AbstractBeanFactory。有點繞,其實就是 DefaultListableBeanFactory 的爺爺…
【重載】getBean
AbstractBeanFactory#getBean
通過名稱獲取 Bean,這個名稱可以是 ID,也可以是別名。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } @Override public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); } @Override public Object getBean(String name, Object... args) throws BeansException { return doGetBean(name, null, args, false); } ... }
getBean 有多個重載方法,可分為通過 Bean 名稱或通過 Class 獲取 Bean 對象,這些重載方法底層都是調(diào)用 doGetBean 方法。
【從緩存拿或者創(chuàng)建】doGetBean
AbstractBeanFactory#doGetBean
// 為了簡潔美觀,這里將源碼中的部分非核心內(nèi)容進行了刪減 protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) { // 轉(zhuǎn)換名稱,返回 Bean 的 ID // 如果是 FactoryBean 類型,則參數(shù) name 會以 & 為前綴。此方法會去掉該修飾符,并返回后面的內(nèi)容 // 如果傳入的是 Bean 的別名,則會找到 Bean 的 ID 返回 final String beanName = transformedBeanName(name); Object bean; // 單例 Bean 只會被創(chuàng)建一次,后續(xù)再獲取 Bean,直接從單例緩存中獲?。ü灿腥壘彺妫? Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 如果存在緩存的 Bean // 獲取 Bean,正常 Bean 直接返回,如果是 FactoryBean 則返回 FactoryBean.getObject() bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 檢驗邏輯 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(...); } // 父子容器的處理 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 當(dāng)父容器不為空并且獲取的 Bean 不在子容器定義時,從父容器遞歸獲取 String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // 遞歸到父容器中尋找 return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { // 將 Bean 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎?chuàng)建),即將 beanName 加入 alreadyCreated 集合 markBeanAsCreated(beanName); } try { // 獲取合并后的父子 Bean,對應(yīng) <bean id="p" abstract="true"> 和 <bean id="c" parent="p" 的用法 // 將子標(biāo)簽 bean 的各個屬性合并到父標(biāo)簽,生成 RootBeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 獲取目標(biāo) bean 所依賴的其它 bean 名稱 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(...); } // 若存在依賴則需要遞歸實例化依賴的 bean registerDependentBean(dep, beanName); try { getBean(dep); } // catch... } } if (mbd.isSingleton()) { // 創(chuàng)建單例 Bean sharedInstance = getSingleton(beanName, () -> { try { // 創(chuàng)建 Bean 的核心方法 return createBean(beanName, mbd, args); } // catch... }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // 創(chuàng)建原型 Bean Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // 創(chuàng)建其他作用域的 Bean String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException(...); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } // catch... } } // catch... } // 將 Bean 的類型轉(zhuǎn)換為 getBean 時指定的 requireType 類型 if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(...); } return convertedBean; } // catch... } return (T) bean; }
簡單概述一下整個過程:
- 第一步【轉(zhuǎn)換名稱】:解析轉(zhuǎn)換傳入的獲取 Bean 的名字,可以分為三種情況:
- 傳入的直接是 ID,則無須轉(zhuǎn)換
- 傳入的是 Bean 的別名,轉(zhuǎn)換成 Bean 的 ID 返回
- 傳入的是 FactoryBean 的
&
寫法,,轉(zhuǎn)換成 Bean 的 ID 返回
- 第二步【從緩存中獲取】:單例作用域的 Bean 只會創(chuàng)建一次,之后會存儲在 Spring 的緩存中(共計三層)。如果緩存中存在目標(biāo) Bean,則獲取 Bean,正常 Bean 直接返回,如果是 FactoryBean 則 返回 FactoryBean.getObject()。獲取到 Bean 之后跳到第八步【類型轉(zhuǎn)換】。
- 第三步【父子容器的處理】:如果沒有從上面的緩存中拿到數(shù)據(jù),說明這次要重新創(chuàng)建 Bean。首先進行父子容器的處理,當(dāng)父容器不為空并且獲取的 Bean 不在當(dāng)前容器定義時,從父容器遞歸獲取。
- 第四步【標(biāo)記 Bean 為被創(chuàng)建】:將 Bean 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎?chuàng)建),即將 beanName 加入 alreadyCreated 集合。
- 第五步【合并父子 Bean】:獲取合并后的父子 Bean,對應(yīng)
<bean id="xx" abstract="true">
和<bean id="c" parent="xx"
的用法,這個步驟會將子標(biāo)簽 bean 的各個屬性合并到父標(biāo)簽,生成 RootBeanDefinition。 - 第六步【處理依賴 Bean】:獲取當(dāng)前 Bean 是否配置依賴的其他的 Bean 的名稱,若存在依賴則需要遞歸實例化依賴的其他 Bean。這個用法現(xiàn)在已經(jīng)很少了,大家可以忽略。
- 第七步【根據(jù)作用域創(chuàng)建 Bean】:根據(jù)作用域可分為三類:單例(singleton)、原型(prototype)和其他,對應(yīng)的 if 的三個分支,最后都會調(diào)用 createBean 創(chuàng)建 Bean。
- 第八步【類型轉(zhuǎn)換】:如果獲取 Bean 的時候傳入了期望轉(zhuǎn)換的類型 Class,那么這一步就會進行類型轉(zhuǎn)換,之后就將創(chuàng)建的 Bean 返回給調(diào)用者了。
以上就是 getBean 方法的大致流程,其中有兩個頻繁出現(xiàn)且非常重要的方法,一個是處理 FactoryBean 的 getObjectForBeanInstance方法,另一個是創(chuàng)建 Bean 的核心實現(xiàn) createBean 方法。
當(dāng)某個 Bean 的實例化過程比較復(fù)雜時,可通過實現(xiàn) FactoryBean 接口,然后在重寫的 getObject 方法中定義實例化 Bean 的邏輯,以后獲取該 Bean 時,會通過調(diào)用 getObject 方法進行返回。值得注意的是 MyBatis 底層就是通過 FactoryBean 來實現(xiàn)。
【BeanFactory處理】getObjectForBeanInstance
AbstractBeanFactory#getObjectForBeanInstance
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // 如果 beanName 以 & 為前綴,但對應(yīng)的 Bean 不是 FactoryBean 類型,則拋異常 if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(...); } } // 校驗已獲取的 Bean // 1、如果該 Bean 不是 FactoryBean 類型,直接返回 // 2、如果是 FactoryBean 類型,且 beanName 以 & 為前綴,說明想獲取的是 FactoryBean,也是直接返回 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } // 從緩存中嘗試獲取 FactoryBean 創(chuàng)建的對象 Object object = null; if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // 到這里已確定 beanInstance 一定是 FactoryBean 類型,所以進行強轉(zhuǎn) FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // 獲取 Bean 對應(yīng)的 BeanDefinition if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } // 當(dāng)前 Bean 是否是用戶定義的,而不是應(yīng)用程序自己定義的 boolean synthetic = (mbd != null && mbd.isSynthetic()); // 解析 FactoryBean 的核心方法 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
這個方法很簡單,大多是些輔助代碼以及一些功能性的判斷,真正的核心代碼在 getObjectFromFactoryBean 方法中。
【BeanFactory處理】getObjectFromFactoryBean
AbstractBeanFactory#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { // 如果是單例 Bean if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { // 嘗試從緩存中獲取,緩存中存儲的是已經(jīng)通過 FactoryBean 創(chuàng)建的 bean Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { // 通過 FactoryBean 創(chuàng)建真正的 Bean,其實就是調(diào)用了 factory.getObject() 方法 object = doGetObjectFromFactoryBean(factory, beanName); // 這里大概是在執(zhí)行上一步 doGetObjectFromFactoryBean 方法過程中,該 bean 已被其它線程創(chuàng)建并緩存了起來 Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // 如果沒有 if (shouldPostProcess) { // Bean 是否要進行后置處理 ... try { // 執(zhí)行后置處理器 object = postProcessObjectFromFactoryBean(object, beanName); } // catch ... } ... } } return object; } } else { // 如果不是單例 bean // 通過 FactoryBean 創(chuàng)建真正的 bean Object object = doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) { try { // 執(zhí)行后置處理器 object = postProcessObjectFromFactoryBean(object, beanName); } // catch ... } return object; } }
【創(chuàng)建Bean的入口】createBean
AbstractAutowireCapableBeanFactory#createBean
接著進入創(chuàng)建 Bean 的下一步 createBean 方法:
這個 createBean 方法是定義在 AbstractBeanFactory 中的抽象方法,最終的實現(xiàn)是交給了 AbstractAutowireCapableBeanFactory 類實現(xiàn),所以接下來我們看看 AbstractAutowireCapableBeanFactory 這個類。
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) { RootBeanDefinition mbdToUse = mbd; // 根據(jù)設(shè)置的 class 屬性或 className 來解析得到 Class 引用賦值給 RootBeanDefinition if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // 對 override 屬性進行標(biāo)記和驗證,本質(zhì)上是處理 lookup-method 和 replaced-method 標(biāo)簽 try { mbdToUse.prepareMethodOverrides(); } // catch... try { // 執(zhí)行 BeanPostProcessors 后置處理器,如果有 Bean 返回,則不執(zhí)行接下來創(chuàng)建 Bean 的操作,直接返回該 Bean // 實際上這里的代碼是不走的 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } // catch... try { // 最后會執(zhí)行到這里,這是創(chuàng)建 Bean 的核心方法 Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; } // catch... }
【創(chuàng)建Bean的主邏輯】doCreateBean
AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) { BeanWrapper instanceWrapper = null; // 如果是單例,嘗試獲取對應(yīng)的 BeanWrapper if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 這里是一個關(guān)鍵點,使用對應(yīng)的策略(工廠方法、構(gòu)造函數(shù))創(chuàng)建 Bean 實例,以及簡單初始化 // BeanWrapper 包裝了 Bean 對象,并封裝類型轉(zhuǎn)換器 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 從 BeanWrapper 中獲取包裝的 Bean 實例 final Object bean = instanceWrapper.getWrappedInstance(); // 從 BeanWrapper 獲取包裝 Bean 的 Class 引用 Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 執(zhí)行 MergedBeanDefinitionPostProcessor 后置處理器。 synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } // catch... mbd.postProcessed = true; } } // 檢查是否需要提前曝光,避免循環(huán)依賴(循環(huán)依賴問題會在后面詳細討論) boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 開始初始化 Bean Object exposedObject = bean; try { // 對 Bean 進行填充,將各個屬性值注入,如果存在依賴的 Bean 則進行遞歸初始化 populateBean(beanName, mbd, instanceWrapper); // 執(zhí)行一系列的初始化方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } // catch... // 再次檢查是否循環(huán)依賴 if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { // throw } } } } // 注冊 DisposableBean try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } // catch... return exposedObject; }
該方法整體流程如下:
- 如果是單例,嘗試從緩存中獲取 Bean 的包裝器 BeanWrapper,并清除緩存
- 如果不存在對應(yīng)的 Wrapper,則說明 Bean 未被實例化,創(chuàng)建 Bean 實例
- 執(zhí)行 MergedBeanDefinitionPostProcessor 后置處理器
- 檢查是否需要提前曝光,避免循環(huán)依賴
- 屬性填充,將所有屬性填充至 Bean 的實例中
- 執(zhí)行一系列的初始化方法(回調(diào)鉤子接口)
- 再次檢查是否存在循環(huán)依賴
- 注冊 DisposableBean
該過程中有幾個需要重點介紹的方法,分別是創(chuàng)建 Bean 實例的 createBeaninstance 方法、注入 Bean 屬性的 populateBean 方法以及執(zhí)行 Bean 初始化方法的 initializeBean 方法。
【創(chuàng)建Bean的核心邏輯】createBeaninstance
AbstractAutowireCapableBeanFactory#createBeaninstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(...); } // 如果有用于創(chuàng)建 Bean 實例的回調(diào)方法 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 如果工廠方法不為空,則使用工廠方法進行實例化 if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 利用構(gòu)造函數(shù)進行實例化,解析并確定目標(biāo)構(gòu)造函數(shù) boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { // 一個類可能有多個構(gòu)造函數(shù),需要根據(jù)參數(shù)來確定具體的構(gòu)造函數(shù) if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } // 如果已經(jīng)解析過,則使用已經(jīng)確定的構(gòu)造方法 if (resolved) { if (autowireNecessary) { // 依據(jù)構(gòu)造函數(shù)注入 return autowireConstructor(beanName, mbd, null, null); } else { // 使用默認構(gòu)造函數(shù)構(gòu)造 return instantiateBean(beanName, mbd); } } // 根據(jù)參數(shù)確定構(gòu)造函數(shù) Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // 使用默認的構(gòu)造函數(shù) return instantiateBean(beanName, mbd); }
以上主要分為:
- 使用工廠方法進行實例化
- 通過構(gòu)造函數(shù)實例化
不管是通過工廠方法還是構(gòu)造方法來實例化對象,到這里得到的也僅僅是一個 Bean 的最初實例,還不是我們最終期望的 Bean,因為后面還需要對 Bean 實例進行初始化處理,注入相應(yīng)的屬性值等。
【屬性填充】populateBean
AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 判斷實例化的 Bean 是否為空 if (bw == null) { // 返回是否有為此 Bean 定義的屬性值,如果有,則拋異常,提示 “無法將屬性值應(yīng)用于空實例” if (mbd.hasPropertyValues()) { throw new BeanCreationException(...); } // 沒有,則跳過屬性填充階段以獲取空實例 else { return; } } // 在設(shè)置屬性之前,先執(zhí)行 InstantiationAwareBeanPostProcessors 后置處理器,這些后置處理器可以用其它方式注入屬性,如字段注入。 boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } // 當(dāng)使用了 InstantiationAwareBeanPostProcessors 后置處理器注入屬性,則結(jié)束屬性注入流程,直接返回 if (!continueWithPropertyPopulation) { return; } // 獲取 Bean 實例的屬性值集合 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 根據(jù)名稱自動注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 根據(jù)類型自動注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // 返回此工廠是否擁有 InstantiationAwareBeanPostProcessor boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 是否進行依賴檢查 boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { if (pvs == null) { pvs = mbd.getPropertyValues(); } PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); // 在屬性注入前執(zhí)行 InstantiationAwareBeanPostProcessor 后置處理器 // @Autoware 的實現(xiàn)原理 // 這里涉及一個極其重要的后置處理器實現(xiàn) AutowiredAnnotationBeanPostProcessor,其主要用來處理 @Autowired 注解,這部分會在后面詳細討論 if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } // 進行依賴檢查 if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } if (pvs != null) { // 這里進行屬性的類型轉(zhuǎn)換,例如將字符串的 id 轉(zhuǎn)為數(shù)字的 id // 執(zhí)行屬性注入,這里才真正的將屬性進行填充,將解析和類型轉(zhuǎn)換好的屬性列表(pvs)賦值到包裝對象(bw)上 applyPropertyValues(beanName, mbd, bw, pvs); } }
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { // ... // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { // 遍歷解析到的每個屬性 if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); // 如果是 JDK 類型,返回的是 TypeStringValue // 如果是要注入其他的 Bean,則是 RuntimeBeanReference 類型 Object originalValue = pv.getValue(); // 這里是個重點,進行屬性的解析,如果是 JDK 類型則返回的對應(yīng) JDK 的類型 // 如果是 RuntimeBeanReference,則會遞歸調(diào)用工廠的 getBean 獲取到要注入的對象 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { // 進行類型準(zhǔn)換 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } if (resolvedValue == originalValue) { if (convertible) { // 將類型轉(zhuǎn)換好的數(shù)據(jù)賦值給 PropertyValue pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } try { // 這里才真正的對創(chuàng)建的包裝對象進行了屬性的賦值,底層肯定是用到了反射了 bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
【初始化】initializeBean
AbstractAutowireCapableBeanFactory#initializeBean
接著進入 initializeBean 方法,在該方法中會回調(diào)許多在 Bean 初始化階段執(zhí)行的方法。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { // 回調(diào) Aware 系列接口 if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } // 回調(diào) BeanPostProcessor 后置處理器的 postProcessBeforeInitialization 方法 Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 回調(diào) InitializingBean 的 afterPropertiesSet 方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 回調(diào) BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
可以看到,在 Bean 的初始化階段,分別回調(diào)了 Aware 系列接口、BeanPostProcessor 后置處理器、InitializingBean。這三個接口都屬于 Spring 的鉤子接口,是 Spring 開放出來的擴展接口,可以影響 Bean 的生命周期。
回調(diào) Aware 系列接口
private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { // 如果當(dāng)前 Bean 繼承了 BeanNameAware 接口,則回調(diào)接口中的 setBeanName 方法,并傳遞 beanName 參數(shù) if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } // 這個 BeanClassLoaderAware 接口傳遞的是 ClassLoader if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } // 這個 BeanFactoryAware 接口傳遞的是 AbstractAutowireCapableBeanFactory if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
這里被回調(diào)的 Aware 接口有三個,分別是 BeanNameAware 、BeanClassLoaderAware、BeanFactoryAware。
回調(diào) BeanPostProcessor 后置處理器的 postProcessBeforeInitialization 方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) { Object result = existingBean; // getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實現(xiàn) // 并循環(huán)執(zhí)行 postProcessBeforeInitialization 方法,參數(shù)是當(dāng)前 Bean 以及 beanName for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
其中有一個后置處理器的實現(xiàn) ApplicationContextAwareProcessor ,其用來對剩余的 Aware 接口進行回調(diào):
@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); } } }
回調(diào) InitializingBean 的 afterPropertiesSet 方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { //.. ((InitializingBean) bean).afterPropertiesSet(); //.. }
回調(diào) BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法
@Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) { Object result = existingBean; // getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實現(xiàn) // 并循環(huán)執(zhí)行 postProcessAfterInitialization 方法,參數(shù)是當(dāng)前 Bean 以及 beanName for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
注意 Spring AOP 就是通過 BeanPostProcessor 來實現(xiàn)的,創(chuàng)建代理對象就是在初始化階段執(zhí)行 postProcessAfterInitialization 中完成的,有一個 AspectJAwareAdvisorAutoProxyCreator 這個類。
到這里,創(chuàng)建 Bean 的核心流程就討論結(jié)束,我這里做一個完整的歸納:
- 調(diào)用者通過 getBean 方法調(diào)用工廠獲取一個 Bean,傳入的 name 可以是 Bean 的 id;也可以是別名;也可以是 &name,表示獲取原始的 FactoryBean 對象。
- 通過一系列的方法重載,最后會到達 AbstractBeanFactory#doGetBean 方法處理,先要對傳入的 name 進行解析,解析出 id。
- 接下來會嘗試從單例緩存池中獲取已創(chuàng)建好的對象,Spring 底層提供了三級緩存(三個Map)體系來解決循環(huán)依賴的問題:singletonObjects、earlySingletonObjects、singletonFactories。
- 如果拿到了緩存數(shù)據(jù):對 FactoryBean 類型進行判定,決定是否直接返回緩存對象還是返回 FactoryBean.getObject()。
- 如果沒有拿到緩存數(shù)據(jù),說明要新建一個 Bean。
- 首先進行父子容器的處理,當(dāng)父容器不為空并且獲取的 Bean 不在子容器定義時,從父容器遞歸獲取。
- 將 Bean 標(biāo)記為已經(jīng)創(chuàng)建(或?qū)⒁獎?chuàng)建),即將 beanName 加入 alreadyCreated 集合。
- 父子 Bean 的處理,將子標(biāo)簽 bean 的各個屬性合并到父標(biāo)簽,生成 RootBeanDefinition。
- 處理 depends-on,若存在依賴則需要遞歸實例化依賴的 bean。
- 根據(jù)不同的作用域創(chuàng)建 Bean 實例,分為單例、原型和其他,這三種創(chuàng)建的時候都會調(diào)用 createBean 方法,這個方法由 AbstractAutowireCapableBeanFactory 提供。
- 首先需要處理 lookup-method 和 replaced-method。
- 然后要將創(chuàng)建實例的職責(zé)交給 doCreateBean,這個方法大概有三個重要的步驟:
- 創(chuàng)建實例 createBeaninstance:使用工廠方法實例化還是使用構(gòu)造函數(shù),默認是無參構(gòu)造。這里返回的是包裝對象,里面還封裝了類型轉(zhuǎn)換器的信息。
- 屬性填充 populateBean:填充的時候設(shè)計到類型轉(zhuǎn)換,底層再通過反射對創(chuàng)建的包裝對象進行屬性賦值。
- 初始化 initializeBean:在這個步驟,分別回調(diào)了 Aware 系列接口、BeanPostProcessor 后置處理器、InitializingBean。
- 如果 getBean 的時候傳入了類型(
getBean("user", User.clsss)
),則需要進行類型轉(zhuǎn)換后返回。
以上就是超詳細解析Spring Bean的創(chuàng)建過程的詳細內(nèi)容,更多關(guān)于Spring Bean創(chuàng)建過程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
啟動SpringBoot報錯Input length = 1問題及解決
這篇文章主要介紹了啟動SpringBoot報錯Input length = 1問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05SpringCloud Feign Jackson自定義配置方式
這篇文章主要介紹了SpringCloud Feign Jackson自定義配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03Java大批量導(dǎo)出Excel數(shù)據(jù)的優(yōu)化過程
幾十萬上百萬行的數(shù)據(jù)是很常見的。本文主要介紹了Java大批量導(dǎo)出Excel數(shù)據(jù)的優(yōu)化過程,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08關(guān)于SpringCloud?Ribbon替換輪詢算法問題
Spring?Cloud?Ribbon是基于Netlix?Ribbon實現(xiàn)的一套客戶端負載均衡的工具。接下來通過本文給大家介紹SpringCloud?Ribbon替換輪詢算法問題,需要的朋友可以參考下2022-01-01Java面試題沖刺第三十天--數(shù)據(jù)庫(6)
這篇文章主要為大家分享了最有價值的三道關(guān)于數(shù)據(jù)庫的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下2021-09-09