Spring bean 建立過程原始碼解析
相關文章
前言
在上一篇檔案 Spring 中 bean 註冊的原始碼解析 中分析了 Spring 中 bean 的註冊過程,就是把配置檔案中配置的 bean 的資訊載入到記憶體中,以 BeanDefinition 物件的形式存放,該物件中存放了 bean 的相關屬性,下面就以 debug 的形式一步步來看下 bean 是如何建立的。
Spring 中 bean 的建立可以說是非常的複雜,方法巢狀很多,為了更好的理清建立過程,畫了下面的 UML 圖:
從上述 UML 圖中,可以看出 bean 的建立主要分為以下幾步:
1. 根據 bean 的 name 解析對應的 class
2. 處理 lookup-metod 和 replace-method 子標籤
3. 處理初始化前的後置處理器
4. 真正的建立 bean
4.1 建立 bean 例項
4.1.1 工廠方法建立
4.1.2 帶引數的構造方法建立
4.1.3 預設的構造方法建立
4.2
4.3 新增單例物件的工廠快取
4.4 填充物件的各種屬性
4.4.1 名稱注入
4.4.2 型別注入
4.5 處理 init-method 方法
4.5.1 處理 bean 的前置處理器
4.5.2 執行 init-method 方法
4.5.3 處理 bean 的後置處理器
建立過程
建立 bean 的程式碼是在 AbstractAutowireCapableBeanFactory 類中開始建立的,在分析的過程中,會把一些程式碼省略掉,如異常處理等:
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { // 表示 <bean> 標籤,裡面有各種屬性 RootBeanDefinition mbdToUse = mbd; // 根據設定的 class 屬性或 className 來解析 class, Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // 處理 lookup-method 和 replace-method 子標籤 mbdToUse.prepareMethodOverrides(); // 給 BeanPostProcessors 機會返回一個代理來代替bean的例項 // 即在初始化前,應用後置處理器,解析指定的bean是否存在初始化前的短路操作 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } // 建立 bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; }
處理 lookup-method 和 replace-method 子標籤
這兩個標籤雖然不常用,但是是很有用的,這裡不再細說;在 Spring 中 bean 註冊的原始碼解析 中 這兩個標籤會被解析放到 BeanDefinition 物件的 methodOverrides 屬性中,表示需要覆蓋的方法;所以在建立bean之前需要解析這兩個標籤,但是隻是預處理:
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exists.
MethodOverrides methodOverrides = getMethodOverrides();
if (!methodOverrides.isEmpty()) {
Set<MethodOverride> overrides = methodOverrides.getOverrides();
synchronized (overrides) {
for (MethodOverride mo : overrides) {
prepareMethodOverride(mo);
}
}
}
}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
// 獲取對應類的方法的個數
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException("...");
}
// 標記 MethodOverride 未被覆蓋,避免了後面引數型別檢查的開銷
else if (count == 1) {
mo.setOverloaded(false);
}
}
在處理 prepareMethodOverride(MethodOverride mo) 方法為什麼只處理方法個數為 1 的情況呢?如果一個類中有多個過載的方法,則呼叫或增強的時候,還需要進行引數型別的解析才能確定呼叫的是哪個方法,Spring 把部分功能放在這裡提前進行預處理,如果方法只有一個,即沒有過載的方法,在後面呼叫的時候,直接找到該方法呼叫,不用再去解析引數來確定方法了,這樣就可以避免的一些引數型別檢查的開銷。
例項化的前置處理
如果經過前置處理後的結果不為空,則直接返回,不再進行bean的建立過程,AOP功能就是在這裡判斷的:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// bean 的前置處理器
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// bean 的後置處理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
建立 bean
當經過 resolveBeforeInstantiation 方法後,如果程式建立了代理,或者執行了 applyBeanPostProcessorsBeforeInstantiation 和 applyBeanPostProcessorsAfterInitialization 方法後,bean 被改變了,則直接返回,否則,會進行建立bean操作:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {
// 最終返回的 bean 的包裝類
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 如果是單例,則檢查工廠快取中以前是否建立過
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 建立bean,工廠方法建立,構造方法建立,預設構造方法建立等
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
// 應用 MergedBeanDefinitionPostProcessors
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// 檢查迴圈依賴:是否是單例 && 是否允許迴圈依賴 && 當前bean是否正在建立中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 為了避免後期的迴圈依賴,在bean初始化完成前,將建立bean的工廠新增到快取中,如果其他的bean依賴該bean,直接從快取中獲取對應的工廠建立集合,解決迴圈依賴,注意是隻有單例情況才能這麼做
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 初始化 bean
Object exposedObject = bean;
// 填充屬性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 執行初始化方法,如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
if (earlySingletonExposure) {
// 只有在檢測到迴圈依賴時才不會為空
Object earlySingletonReference = getSingleton(beanName, false);
// 存在迴圈依賴
if (earlySingletonReference != null) {
// 如果 exposedObject 在初始化方法中沒有被改變,即沒有被增強
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 檢測依賴
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 因為bean建立後,所依賴的bean一定是已經建立完畢的,actualDependentBeans 不為空則表示所依賴的bean還沒有建立完,即存在迴圈依賴
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException("");
}
}
}
}
// 根據 score 註冊 bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
上面建立 bean 的過程很複雜,分為很多步驟,下面再來看看這些步驟:
建立bean例項
建立 bean 的例項,會根據策略使用不同的建立方法,比如說 構造方法建立, 工廠方法建立,預設的構造方法建立等:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 獲取 bean 對應的 class
Class<?> beanClass = resolveBeanClass(mbd, 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);
}
引數的構造方法注入
先來看下帶引數的構造方法自動注入,
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// explicitArgs 引數通過 getBean() 方法傳入,Object getBean(String name, Object... args)
if (explicitArgs != null) {
// 如果 getBean 方法傳入了引數,則直接使用
argsToUse = explicitArgs;
}
else {
// 如果 getBean 方法沒有傳入引數,則從配置檔案進行解析
Object[] argsToResolve = null;
// 從快取中獲取
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
// 配置的構造方法引數
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
// 該構造沒有被快取,則需要進行解析
if (constructorToUse == null) {
boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
// 引數個數
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// 獲取配置檔案中配置的構造方法引數
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 獲取引數個數
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
// 排序構造方法,按照引數個數進行排序
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
for (Constructor<?> candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
if (constructorToUse != null && argsToUse.length > paramTypes.length) {
// 如果已經找到滿足條件的構造方法,則終止
break;
}
if (paramTypes.length < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
// 構造方法引數的名字
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
// 如果引數名字為空,則獲取引數名稱探索器
ParameterNameDiscoverer pnd=this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
// 使用探索器獲取對應構造方法的引數名稱
paramNames = pnd.getParameterNames(candidate);
}
// 根據引數名稱和型別建立引數持有者
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,getUserDeclaredConstructor(candidate), autowiring);
}
else {
// 構造方法沒有引數
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 檢查是否有不確定性構造方法的存在,如引數為父子關係
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
throw new BeanCreationException("...")
}
// 將解析的構造方法加入快取
if (explicitArgs == null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
// 例項化
Object beanInstance;
if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
}
}, beanFactory.getAccessControlContext());
}
else {
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
bw.setBeanInstance(beanInstance);
return bw;
}
上面的方法就是使用構造方法進行例項化bean的過程,很複雜,也有很多的輔助方法,下面來看下例項化的過程:
例項化有兩種方式,CGLIB 和 反射:
beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, beanFactory, ctorToUse);
先來看下 getInstantiationStrategy 方法返回什麼?
protected InstantiationStrategy getInstantiationStrategy() {
return this.instantiationStrategy;
}
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
它返回的是 InstantiationStrategy 介面,而介面由兩個實現類:
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
// 如果沒有需要動態改變的方法,則直接使用反射進行例項化
if (bd.getMethodOverrides().isEmpty()) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
ReflectionUtils.makeAccessible(ctor);
return null;
}
});
}
// 使用 反射 例項化
return BeanUtils.instantiateClass(ctor, args);
}
else {
// 如果需要覆蓋或者動態替換的方法,則需要使用 CGLIB 來動態代理,在建立代理的時候,可以增強植入我們的程式碼
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
使用工廠方法建立例項和構造方法參不多,使用預設的構造方法例項化比較簡單,這裡就不列出來了。
屬性填充
在上面分析 doCreateBean 方法的時候,當通過 工廠方法,帶引數的構造方法或預設的構造方法建立了 bean 例項後,需要對 bean 的屬性進行設定
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// 給 InstantiationAwareBeanPostProcessor 最後一次機會在屬性設定前來改變 bean
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// postProcessAfterInstantiation 返回值為是否繼續填充 bean
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
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;
}
// 後處理器已經初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 需要依賴檢查
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
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);
}
}
// 將屬性應用到 bean 中
applyPropertyValues(beanName, mbd, bw, pvs);
}
關於 名稱 注入和型別注入,後面單獨分析
將屬性應用到 bean 中:
到這裡,已經完成了對注入屬性的獲取,但是獲取的是 PropereyValues 的形式存在,現在將他們應用到 bean 中去:
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
// 如果 mpvs 中的值已經被轉換為對應的型別,則可以直接設定到 beanWapper 中
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
bw.setPropertyValues(mpvs);
return;
}
original = mpvs.getPropertyValueList();
}
else {
// 如果 pvs 不是 MutablePropertyValues 封裝的類,則直接使用原始的屬性獲取方法
original = Arrays.asList(pvs.getPropertyValues());
}
// 獲取使用者自定義的型別轉換器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
/ 獲取對應的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
boolean resolveNecessary = false;
// 遍歷屬性,將屬性轉換為對應類的對應屬性的型別
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
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) {
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();
}
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
執行初始化方法
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 執行使用者自定義的各種 aware 方法
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 在執行 init 方法之前,先執行 前置處理器 applyBeanPostProcessorsBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 執行初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
// 執行後置處理器 applyBeanPostProcessorsAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
// 執行使用者自定義的各種 aware 方法
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);
}
}
}
到這裡,bean 建立的大致過程就結束了