超詳細解析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 閱讀器,并指定關聯(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") 對應的實現,這個創(chuàng)建邏輯可以說是 Spring 中最復雜的地方,其中會完整的體現上面生命周期的各個步驟,以及對單例對象、多實例對象的處理,接下來我們將深入源碼,解析整個對象的創(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 對象,這些重載方法底層都是調用 doGetBean 方法。
【從緩存拿或者創(chuàng)建】doGetBean
AbstractBeanFactory#doGetBean
// 為了簡潔美觀,這里將源碼中的部分非核心內容進行了刪減
protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
// 轉換名稱,返回 Bean 的 ID
// 如果是 FactoryBean 類型,則參數 name 會以 & 為前綴。此方法會去掉該修飾符,并返回后面的內容
// 如果傳入的是 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)) {
// 當父容器不為空并且獲取的 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 標記為已經創(chuàng)建(或將要創(chuàng)建),即將 beanName 加入 alreadyCreated 集合
markBeanAsCreated(beanName);
}
try {
// 獲取合并后的父子 Bean,對應 <bean id="p" abstract="true"> 和 <bean id="c" parent="p" 的用法
// 將子標簽 bean 的各個屬性合并到父標簽,生成 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 獲取目標 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 的類型轉換為 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;
}

簡單概述一下整個過程:
- 第一步【轉換名稱】:解析轉換傳入的獲取 Bean 的名字,可以分為三種情況:
- 傳入的直接是 ID,則無須轉換
- 傳入的是 Bean 的別名,轉換成 Bean 的 ID 返回
- 傳入的是 FactoryBean 的
&寫法,,轉換成 Bean 的 ID 返回
- 第二步【從緩存中獲取】:單例作用域的 Bean 只會創(chuàng)建一次,之后會存儲在 Spring 的緩存中(共計三層)。如果緩存中存在目標 Bean,則獲取 Bean,正常 Bean 直接返回,如果是 FactoryBean 則 返回 FactoryBean.getObject()。獲取到 Bean 之后跳到第八步【類型轉換】。
- 第三步【父子容器的處理】:如果沒有從上面的緩存中拿到數據,說明這次要重新創(chuàng)建 Bean。首先進行父子容器的處理,當父容器不為空并且獲取的 Bean 不在當前容器定義時,從父容器遞歸獲取。
- 第四步【標記 Bean 為被創(chuàng)建】:將 Bean 標記為已經創(chuàng)建(或將要創(chuàng)建),即將 beanName 加入 alreadyCreated 集合。
- 第五步【合并父子 Bean】:獲取合并后的父子 Bean,對應
<bean id="xx" abstract="true">和<bean id="c" parent="xx"的用法,這個步驟會將子標簽 bean 的各個屬性合并到父標簽,生成 RootBeanDefinition。 - 第六步【處理依賴 Bean】:獲取當前 Bean 是否配置依賴的其他的 Bean 的名稱,若存在依賴則需要遞歸實例化依賴的其他 Bean。這個用法現在已經很少了,大家可以忽略。
- 第七步【根據作用域創(chuàng)建 Bean】:根據作用域可分為三類:單例(singleton)、原型(prototype)和其他,對應的 if 的三個分支,最后都會調用 createBean 創(chuàng)建 Bean。
- 第八步【類型轉換】:如果獲取 Bean 的時候傳入了期望轉換的類型 Class,那么這一步就會進行類型轉換,之后就將創(chuàng)建的 Bean 返回給調用者了。
以上就是 getBean 方法的大致流程,其中有兩個頻繁出現且非常重要的方法,一個是處理 FactoryBean 的 getObjectForBeanInstance方法,另一個是創(chuàng)建 Bean 的核心實現 createBean 方法。
當某個 Bean 的實例化過程比較復雜時,可通過實現 FactoryBean 接口,然后在重寫的 getObject 方法中定義實例化 Bean 的邏輯,以后獲取該 Bean 時,會通過調用 getObject 方法進行返回。值得注意的是 MyBatis 底層就是通過 FactoryBean 來實現。
【BeanFactory處理】getObjectForBeanInstance
AbstractBeanFactory#getObjectForBeanInstance
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 如果 beanName 以 & 為前綴,但對應的 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 類型,所以進行強轉
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// 獲取 Bean 對應的 BeanDefinition
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
// 當前 Bean 是否是用戶定義的,而不是應用程序自己定義的
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()) {
// 嘗試從緩存中獲取,緩存中存儲的是已經通過 FactoryBean 創(chuàng)建的 bean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 通過 FactoryBean 創(chuàng)建真正的 Bean,其實就是調用了 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 中的抽象方法,最終的實現是交給了 AbstractAutowireCapableBeanFactory 類實現,所以接下來我們看看 AbstractAutowireCapableBeanFactory 這個類。
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {
RootBeanDefinition mbdToUse = mbd;
// 根據設置的 class 屬性或 className 來解析得到 Class 引用賦值給 RootBeanDefinition
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 對 override 屬性進行標記和驗證,本質上是處理 lookup-method 和 replaced-method 標簽
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;
// 如果是單例,嘗試獲取對應的 BeanWrapper
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 這里是一個關鍵點,使用對應的策略(工廠方法、構造函數)創(chuàng)建 Bean 實例,以及簡單初始化
// BeanWrapper 包裝了 Bean 對象,并封裝類型轉換器
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,并清除緩存
- 如果不存在對應的 Wrapper,則說明 Bean 未被實例化,創(chuàng)建 Bean 實例
- 執(zhí)行 MergedBeanDefinitionPostProcessor 后置處理器
- 檢查是否需要提前曝光,避免循環(huán)依賴
- 屬性填充,將所有屬性填充至 Bean 的實例中
- 執(zhí)行一系列的初始化方法(回調鉤子接口)
- 再次檢查是否存在循環(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 實例的回調方法
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果工廠方法不為空,則使用工廠方法進行實例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 利用構造函數進行實例化,解析并確定目標構造函數
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 一個類可能有多個構造函數,需要根據參數來確定具體的構造函數
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已經解析過,則使用已經確定的構造方法
if (resolved) {
if (autowireNecessary) {
// 依據構造函數注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默認構造函數構造
return instantiateBean(beanName, mbd);
}
}
// 根據參數確定構造函數
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 使用默認的構造函數
return instantiateBean(beanName, mbd);
}
以上主要分為:
- 使用工廠方法進行實例化
- 通過構造函數實例化
不管是通過工廠方法還是構造方法來實例化對象,到這里得到的也僅僅是一個 Bean 的最初實例,還不是我們最終期望的 Bean,因為后面還需要對 Bean 實例進行初始化處理,注入相應的屬性值等。
【屬性填充】populateBean
AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 判斷實例化的 Bean 是否為空
if (bw == null) {
// 返回是否有為此 Bean 定義的屬性值,如果有,則拋異常,提示 “無法將屬性值應用于空實例”
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(...);
}
// 沒有,則跳過屬性填充階段以獲取空實例
else {
return;
}
}
// 在設置屬性之前,先執(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;
}
}
}
}
// 當使用了 InstantiationAwareBeanPostProcessors 后置處理器注入屬性,則結束屬性注入流程,直接返回
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);
// 根據名稱自動注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根據類型自動注入
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 的實現原理
// 這里涉及一個極其重要的后置處理器實現 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) {
// 這里進行屬性的類型轉換,例如將字符串的 id 轉為數字的 id
// 執(zhí)行屬性注入,這里才真正的將屬性進行填充,將解析和類型轉換好的屬性列表(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 類型則返回的對應 JDK 的類型
// 如果是 RuntimeBeanReference,則會遞歸調用工廠的 getBean 獲取到要注入的對象
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
// 進行類型準換
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
if (resolvedValue == originalValue) {
if (convertible) {
// 將類型轉換好的數據賦值給 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 方法,在該方法中會回調許多在 Bean 初始化階段執(zhí)行的方法。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 回調 Aware 系列接口
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 回調 BeanPostProcessor 后置處理器的 postProcessBeforeInitialization 方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 回調 InitializingBean 的 afterPropertiesSet 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 回調 BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
可以看到,在 Bean 的初始化階段,分別回調了 Aware 系列接口、BeanPostProcessor 后置處理器、InitializingBean。這三個接口都屬于 Spring 的鉤子接口,是 Spring 開放出來的擴展接口,可以影響 Bean 的生命周期。
回調 Aware 系列接口
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
// 如果當前 Bean 繼承了 BeanNameAware 接口,則回調接口中的 setBeanName 方法,并傳遞 beanName 參數
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);
}
}
}
這里被回調的 Aware 接口有三個,分別是 BeanNameAware 、BeanClassLoaderAware、BeanFactoryAware。
回調 BeanPostProcessor 后置處理器的 postProcessBeforeInitialization 方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) {
Object result = existingBean;
// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實現
// 并循環(huán)執(zhí)行 postProcessBeforeInitialization 方法,參數是當前 Bean 以及 beanName
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
其中有一個后置處理器的實現 ApplicationContextAwareProcessor ,其用來對剩余的 Aware 接口進行回調:
@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);
}
}
}
回調 InitializingBean 的 afterPropertiesSet 方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//..
((InitializingBean) bean).afterPropertiesSet();
//..
}
回調 BeanPostProcessor 后置處理器的 postProcessAfterInitialization 方法
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) {
Object result = existingBean;
// getBeanPostProcessors 方法獲取所有的 BeanPostProcessor 后置處理器的實現
// 并循環(huán)執(zhí)行 postProcessAfterInitialization 方法,參數是當前 Bean 以及 beanName
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
注意 Spring AOP 就是通過 BeanPostProcessor 來實現的,創(chuàng)建代理對象就是在初始化階段執(zhí)行 postProcessAfterInitialization 中完成的,有一個 AspectJAwareAdvisorAutoProxyCreator 這個類。
到這里,創(chuàng)建 Bean 的核心流程就討論結束,我這里做一個完整的歸納:
- 調用者通過 getBean 方法調用工廠獲取一個 Bean,傳入的 name 可以是 Bean 的 id;也可以是別名;也可以是 &name,表示獲取原始的 FactoryBean 對象。
- 通過一系列的方法重載,最后會到達 AbstractBeanFactory#doGetBean 方法處理,先要對傳入的 name 進行解析,解析出 id。
- 接下來會嘗試從單例緩存池中獲取已創(chuàng)建好的對象,Spring 底層提供了三級緩存(三個Map)體系來解決循環(huán)依賴的問題:singletonObjects、earlySingletonObjects、singletonFactories。
- 如果拿到了緩存數據:對 FactoryBean 類型進行判定,決定是否直接返回緩存對象還是返回 FactoryBean.getObject()。
- 如果沒有拿到緩存數據,說明要新建一個 Bean。
- 首先進行父子容器的處理,當父容器不為空并且獲取的 Bean 不在子容器定義時,從父容器遞歸獲取。
- 將 Bean 標記為已經創(chuàng)建(或將要創(chuàng)建),即將 beanName 加入 alreadyCreated 集合。
- 父子 Bean 的處理,將子標簽 bean 的各個屬性合并到父標簽,生成 RootBeanDefinition。
- 處理 depends-on,若存在依賴則需要遞歸實例化依賴的 bean。
- 根據不同的作用域創(chuàng)建 Bean 實例,分為單例、原型和其他,這三種創(chuàng)建的時候都會調用 createBean 方法,這個方法由 AbstractAutowireCapableBeanFactory 提供。
- 首先需要處理 lookup-method 和 replaced-method。
- 然后要將創(chuàng)建實例的職責交給 doCreateBean,這個方法大概有三個重要的步驟:
- 創(chuàng)建實例 createBeaninstance:使用工廠方法實例化還是使用構造函數,默認是無參構造。這里返回的是包裝對象,里面還封裝了類型轉換器的信息。
- 屬性填充 populateBean:填充的時候設計到類型轉換,底層再通過反射對創(chuàng)建的包裝對象進行屬性賦值。
- 初始化 initializeBean:在這個步驟,分別回調了 Aware 系列接口、BeanPostProcessor 后置處理器、InitializingBean。
- 如果 getBean 的時候傳入了類型(
getBean("user", User.clsss)),則需要進行類型轉換后返回。
以上就是超詳細解析Spring Bean的創(chuàng)建過程的詳細內容,更多關于Spring Bean創(chuàng)建過程的資料請關注腳本之家其它相關文章!
相關文章
啟動SpringBoot報錯Input length = 1問題及解決
這篇文章主要介紹了啟動SpringBoot報錯Input length = 1問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05
SpringCloud Feign Jackson自定義配置方式
這篇文章主要介紹了SpringCloud Feign Jackson自定義配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03

