Spring IoC createBean 方法詳解
- 2020 年 5 月 21 日
- 筆記
- Spring IoC
前言
本篇文章主要分析 Spring IoC 的 createBean()
方法的流程,以及 bean
的生命周期。
下面是一個大致的流程圖:
正文
AbstractAutowireCapableBeanFactory#createBean
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 將String類型的class字符串,轉換為Class對象,例如在XML中配置的class屬性
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 進行定義的方法覆蓋
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 如果bean的實例化前回調方法返回非null,直接返回實例,跳過後面步驟
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 真正去創建bean的方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
// 返回bean的實例
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
上面方法如果 resolveBeforeInstantiation()
返回非 null
,則會跳過後面步驟,直接返回實例。這也是一個擴展點,給 BeanPostProcessor
一個機會來返回代理來替代真正的實例。
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 判斷bean在實例化之前是否已經解析過
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
// 如果bean是合成的 && 有實現 InstantiationAwareBeanPostProcessor 接口
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 解析bean的類型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 執行bean的實例化前回調
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
// 如果實例化前生命周期回調方法返回的不是null
if (bean != null) {
// 執行bean的實例化後回調,因為只能在此處調用了
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 如果bean不為空,則將beforeInstantiationResolved賦值為true,代表在實例化之前已經解析
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
上面方法主要是判斷 bean
之前沒有解析過並且有註冊 InstantiationAwareBeanPostProcessor
接口,然後這裡會調用 bean
實例化前的回調方法,如果返回非空,會調用 bean
實例化後的回調方法;因為返回非空,後續正常的流程都不會走了,所以只能在此處調用。
下面是 InstantiationAwareBeanPostProcessor
接口,如下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* Bean 實例化前調用,返回非 {@code null} 回調過後面流程
* 返回 {@code null} 則進行 IoC 容器對 Bean 的實例化
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/**
* Bean 實例化之後,屬性填充之前調用,返回 {@code true} 則進行默認的屬性填充步驟,
* 返回 {@code false} 會跳過屬性填充階段,同樣也會跳過初始化階段的生命周期方法的回調。
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* Bean 實例化後屬性賦值前調用,PropertyValues 是已經封裝好的設置的屬性值,返回 {@code null} 繼續
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
/**
* 5.1 版本後已經被上面 postProcessProperties 方法所替代,功能與上面方法一樣
*/
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
上面接口提供了三個擴展點,如下:
bean
實例化前bean
實例化後bean
屬性賦值前
這也是 bean
實例化的生命周期回調方法。
AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 如果bean的作用域是singleton,則需要移除未完成的FactoryBean實例的緩存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 通過構造函數反射創建bean的實例,但是屬性並未賦值
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 獲取bean的實例
final Object bean = instanceWrapper.getWrappedInstance();
// 獲取bean的類型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// BeanDefinition 合併後的回調,見下文詳解
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// bean的作用域是單例 && 允許循環引用 && 當前bean正在創建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
// 如果允許bean提前曝光
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 將beanName和ObjectFactory形成的key-value對放入singletonFactories緩存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 給 bean 的屬性賦值
populateBean(beanName, mbd, instanceWrapper);
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 如果允許單例bean提前暴露
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<>(dependentBeans.length);
// 檢測依賴
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// 用於註冊銷毀bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 返回bean實例
return exposedObject;
}
AbstractAutowireCapableBeanFactory#createBeanInstance
/**
* @param args getBean() 中的 args 參數
* @return bean 實例包裝後的 BeanWrapper
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析 bean 的類型
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 判斷beanClass是否是public修飾的類,並且是否允許訪問非公共構造函數和方法,不是拋出異常
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// Spring 5新添加的,如果存在Supplier回調,則使用給定的回調方法初始化策略。可以使RootBeanDefinition#setInstanceSupplier()設置
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果設置工廠方法則使用給定的方法創建bean實例,這裡分為靜態工廠和實例化工廠
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// resolved: 構造函數或工廠方法是否已經解析過
boolean resolved = false;
// autowireNecessary: 是否需要自動注入 (即是否需要解析構造函數)
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 如果resolvedConstructorOrFactoryMethod不為空,代表構造函數或工廠方法已經解析過
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// 根據constructorArgumentsResolved判斷是否需要自動注入
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 如果構造函數或工廠方法已經解析過並且需要自動注入,則執行構造器自動注入,見下文詳解
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 否則使用默認構造函數進行bean實例化,見下文詳解
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 應用後置處理器,SmartInstantiationAwareBeanPostProcessor 拿到 bean 的候選構造函數
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 候選構造函數不為空 || 構造函數依賴注入 || 定義了構造函數的參數值 || args不為空,則執行構造器自動注入
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
// 如果有首選的構造函數,使用該構造函數去創建bean實例
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 沒有特殊處理,使用默認無參構造器實例化bean
return instantiateBean(beanName, mbd);
}
上面代碼主要判斷是使用構函數自動注入,還是使用默認構造函數構造。總結起來以下幾種情況會使用構造函數自動注入:
- 已經緩存過構造函數並且構造函數的參數已經解析過。
- 候選的構造函數不為空,這裡的候選構造函數是通過實現
SmartInstantiationAwareBeanPostProcessor
接口中的determineCandidateConstructors()
- 自動注入模式為構造函數自動注入
BeanDefinition
定義了構造函數參數,如 XML 中的<constructor-arg index="0" value="1"/>
- 在調用
getBean()
時顯示指定了args
參數
AbstractAutowireCapableBeanFactory#instantiateBean
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
// 使用指定的策略去實力化bean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
// 將實例化後的bean封裝成BeanWrapper後返回
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
// SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果有需要覆蓋或者動態替換的方法則當然需要使用CGLIB進行動態代理,因為可以在創建代理的同時將方法織入類中
// 但是如果沒有需要動態改變的方法,為了方便直接用反射就可以了
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 獲取緩存的構造方法或工廠方法
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
// 緩存為空
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
// 如果clazz是接口,拋出異常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
// 獲取默認的無參構造函數
constructorToUse = clazz.getDeclaredConstructor();
}
// 設置緩存
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 這裡就是用指定的無參構造器去實例化該bean,不做具體分析了
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
// 用CGLIB生成子類動態織入重寫的方法
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
上面代碼比較簡單,無非就是使用默認的無參構造器去實例化 bean
,並封裝成 BeanWrapper
返回。
ConstructorResolver#autowireConstructor
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
// 尋找適合的構造器,進行實例化
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// 最終實例化的構造函數
Constructor<?> constructorToUse = null;
// 最終用於實例化的參數Holder
ArgumentsHolder argsHolderToUse = null;
// 最終用於實例化的構造函數參數
Object[] argsToUse = null;
// 如果explicitArgs不為空,則使用explicitArgs當做構造器函數參數
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
// 獲取已經緩存的構造函數或工廠方法
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
// 獲取已經緩存的構造函數參數
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 如果已經緩存了構造函數或工廠方法,那麼resolvedConstructorArguments和preparedConstructorArguments必定有一個緩存了構造函數參數
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
// 如果argsToResolve不為空,則對構造函數參數進行解析,也就是會進行類型轉換之類的操作
// 例如 A(int,int),把配置中的 ("1","1") 轉換為 (1,1)
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
// 如果沒有緩存構造函數或者其參數
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
// 如果允許訪問非public的構造函數和方法(該值默認為 true),就獲取所有構造函數,否則只獲取public修飾的構造函數
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
// 如果只有一個構造函數 && getBean()沒有顯示指定args && 沒有定義構造函數的參數值
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
// 獲取構造函數
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
// 設置構造函數和參數的緩存
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// 通過無參構造函數創建bean的實例,然後直接返回
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// Need to resolve the constructor.
// 如果候選構造函數不為空 || 構造函數自動注入模式
boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
// getBean()顯示指定了參數,獲取參數長度
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// 獲取定義的構造函數參數
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 解析構造函數參數並賦值到resolvedValues,返回參數個數。見下文詳解
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 這裡對構造函數進行排序,規則是首先是public構造函數且參數個數從多到少,然後是非public構造函數且參數個數有多到少
AutowireUtils.sortConstructors(candidates);
// 最小匹配權重,權重越小,越接近我們要找的目標構造函數
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
// 遍歷構造函數,找出符合的構造函數
for (Constructor<?> candidate : candidates) {
// 獲取參數數量
int parameterCount = candidate.getParameterCount();
// 如果已經找到滿足的構造函數 && 目標構造函數參數個數大於當前遍歷的構造函數參數個數則終止
// 因為構造函數已經是排過序的,後面不會再有更適合的了
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
// 如果目標的構造函數參數個數小於我們需要的,直接跳過
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
// 獲取到構造函數的參數類型
Class<?>[] paramTypes = candidate.getParameterTypes();
if (resolvedValues != null) {
try {
// 評估參數名稱,就是判斷構造函數上是否標註了@ConstructorProperties註解,如果標註了,直接取其中定義的參數名稱
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
// 沒有標註@ConstructorProperties註解,使用參數名稱解析器,獲取參數名稱
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
// 創建一個參數數組以調用構造函數或工廠方法,見下文詳解
// 主要是通過參數類型和參數名解析構造函數或工廠方法所需的參數(如果參數是其他bean,則會解析依賴的bean)
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
// resolvedValues為空, explicitArgs不為空,即顯示指定了getBean()的args參數
else {
// Explicit arguments given -> arguments length must match exactly.
// 如果當前構造函數參數個數不等的explicitArgs的長度,直接跳過該構造函數
if (parameterCount != explicitArgs.length) {
continue;
}
// 把explicitArgs封裝進ArgumentsHolder
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 根據mbd的解析構造函數模式(true: 寬鬆模式,false:嚴格模式)
// 將argsHolder的參數和paramTypes進行比較,計算paramTypes的類型差異權重值
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 差異值越小代表構造函數越匹配,則選擇此構造函數
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
// 如果出現權重值更小的候選者,則將ambiguousConstructors清空,允許之前存在權重值相同的候選者
ambiguousConstructors = null;
}
// 兩個候選者權重值相同,並且是當前遍歷過權重值最小的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
// 將兩個候選者添加到ambiguousConstructors
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
// 沒有找到匹配的構造函數,拋出異常
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
// 如果有多個匹配的候選者,並且不是寬鬆模式,拋出異常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousConstructors);
}
// getBean()方法沒有指定args參數 && 構造函數參數不為空
if (explicitArgs == null && argsHolderToUse != null) {
// 緩存解析過後的構造函數和參數
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
// 利用反射創建bean實例
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
上面代碼的功能主要如下:
- 構造函數參數的確定
- 如果
explicitArgs
參數不為空,那就可以直接確定參數。因為explicitArgs
參數是在調用getBean()
時手動指定的,這個主要用於靜態工廠方法的調用。 - 緩存中不為空,那麼可以直接拿過來使用。
BeanDefinition
中讀取,我們所定義的bean
都會生成一個BeanDefinition
,其中記錄了定義了構造函數參數通過getConstructorArgumentValues()
獲取。
- 如果
- 構造函數的確定。經過第一步已經確定構造函數的參數,接下來就是用參數個數在所有的構造函數中鎖定對應的構造函數。匹配之前會對構造函數進行排序,首先是
public
構造函數且參數個數從多到少,然後是非public
構造函數且參數個數有多到少。這樣可以迅速判斷排在後面的構造函數參數個數是否符合條件。 - 根據對應的構造函數轉換對應的參數類型。
- 根據實例化策略以及得到的構造函數和構造函數參數實例化
bean
。
ConstructorResolver#resolveConstructorArguments
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
// 獲取自定義類型轉換器
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
// 如果沒有自定義的轉換器就用bw
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
// minNrOfArgs初始化為indexedArgumentValues+genericArgumentValues的個數總和
int minNrOfArgs = cargs.getArgumentCount();
// 遍歷IndexArgumentValues,這裡的IndexArgumentValues就帶下標的,如:<constructor-arg index="0" value="1"/>
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
int index = entry.getKey();
if (index < 0) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid constructor argument index: " + index);
}
// 如果index大於minNrOfArgs,修改minNrOfArgs值
if (index > minNrOfArgs) {
// 因為index是構造函數下標值,所以總數這邊要加1
minNrOfArgs = index + 1;
}
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
// 如果參數類型已經轉換過,直接添加進resolvedValues
if (valueHolder.isConverted()) {
resolvedValues.addIndexedArgumentValue(index, valueHolder);
}
// 參數類型沒有轉換過,進行轉換
else {
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
// 使用轉換過的參數值構建ValueHolder
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
// 添加進resolvedValues
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
// 遍歷GenericArgumentValues並進行類型轉換和上面一樣,這裡的GenericArgumentValues就是沒有指定下標的,如:<constructor-arg value="1"/>
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
if (valueHolder.isConverted()) {
resolvedValues.addGenericArgumentValue(valueHolder);
}
else {
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
// 返回參數個數
return minNrOfArgs;
}
上面代碼主要將 indexedArgumentValues
和 genericArgumentValues
的值調用 resolveValueIfNecessary()
進行解析;resolveValueIfNecessary()
主要解析參數的類型,比如 ref
屬性引用的 beanName
會通過 getBean()
返回實例。
ConstructorResolver#createArgumentArray
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
// 獲取類型轉換器
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
// 構建ArgumentsHolder
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 遍歷參數類型數組
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
// 獲取參數類型和名稱
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
// 根據參數的下標、類型、名稱查詢是否有匹配的
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
// 沒有匹配的 && 不是自動裝配。嘗試下一個通用的無類型參數值作為降級方法,它可以在類型轉換後匹配 (例如,String -> int)
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
// 找到了匹配的valueHolder
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
// 添加進usedValueHolders
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
// 類型已經轉換過
if (valueHolder.isConverted()) {
// 獲取已經轉換過的值,作為args在paramIndex的預備參數
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
// 類型沒有轉換過
else {
// 將構造方法和參數下標封裝成MethodParameter(MethodParameter是封裝方法和參數索引的工具類)
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
// 將原始值轉換為paramType類型的值,無法轉換時拋出異常
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
// 標記args需要解析
args.resolveNecessary = true;
// 將sourceValue作為args在paramIndex位置的預備參數
args.preparedArguments[paramIndex] = sourceValue;
}
}
// 將convertedValue作為args在paramIndex位置的參數
args.arguments[paramIndex] = convertedValue;
// 將originalValue作為args在paramIndex位置的原始參數
args.rawArguments[paramIndex] = originalValue;
}
// 沒有找到匹配的valueHolder
else {
// 將構造方法和參數下標封裝成MethodParameter
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
// 找不到明確的匹配,並且不是自動注入,拋出異常
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
try {
// 如果是自動注入,用resolveAutowiredArgument()解析參數,見下文詳解
// 構造函數自動注入中的參數bean就是在這邊處理
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
// 將通過自動裝配解析出來的參數賦值給args
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
// 如果依賴了其他的bean,則註冊依賴關係(這邊的autowiredBeanNames,就是所有依賴的beanName)
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
// 返回解析後的參數值
return args;
}
上面代碼判斷構造函數如果有匹配的參數會轉換成對應類型,如果沒有匹配的參數,多半是構造函數自動注入,通過 resolveAutowiredArgument()
去查找 bean
並返回實例。
ConstructorResolver#resolveAutowiredArgument
protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {
// 獲取參數的類型
Class<?> paramType = param.getParameterType();
// 如果參數類型是InjectionPoint
if (InjectionPoint.class.isAssignableFrom(paramType)) {
// 拿到當前的InjectionPoint(存儲了當前正在解析依賴的方法參數信息,DependencyDescriptor)
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
// 當前injectionPoint為空,則拋出異常:目前沒有可用的InjectionPoint
throw new IllegalStateException("No current InjectionPoint available for " + param);
}
// 當前injectionPoint不為空,直接返回
return injectionPoint;
}
try {
// 解析指定依賴,DependencyDescriptor:將MethodParameter的方法參數索引信息封裝成DependencyDescriptor,見下文詳解
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
catch (NoUniqueBeanDefinitionException ex) {
throw ex;
}
catch (NoSuchBeanDefinitionException ex) {
if (fallback) {
// Single constructor or factory method -> let's return an empty array/collection
// for e.g. a vararg or a non-null List/Set/Map parameter.
if (paramType.isArray()) {
return Array.newInstance(paramType.getComponentType(), 0);
}
else if (CollectionFactory.isApproximableCollectionType(paramType)) {
return CollectionFactory.createCollection(paramType, 0);
}
else if (CollectionFactory.isApproximableMapType(paramType)) {
return CollectionFactory.createMap(paramType, 0);
}
}
throw ex;
}
}
上面代碼我們一般只需要重點關注 this.beanFactory.resolveDependency()
這個方法,這個就是解決依賴注入的秘密所在。
DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// Optional類型的處理,說明Spring也可以注入Optional類型的參數
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// ObjectFactory或ObjectProvider類型的處理
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
// javax.inject.Provider類型的處理
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 獲取延遲解析代理
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 解析依賴,返回的result為最終需要注入的bean實例,見下文詳解
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
上面代碼主要判斷如果需要注入的 bean
的類型是 Optional
、ObjectFactory
、ObjectProvider
、Provider
會做特殊的處理,一般情況下注入的 bean
會走最後的 doResolveDependency()
。 還有一個比較重要的參數 DependencyDescriptor
,這個類就是依賴描述符,存儲了需要注入 bean
的類型、構造器參數的下標(構造器注入該值不為空)、是否必需、字段名稱(字段注入該值不為空)、方法名稱(setter
方法注入該值不為空)等。
DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 獲取需要注入bean的快捷方式,不為空直接返回
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 獲取需要注入bean的類型
Class<?> type = descriptor.getDependencyType();
// 用於支持Spring中新增的註解@Value(確定給定的依賴項是否聲明@Value註解,如果有則拿到值)
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 解析MultipleBean,例如 Array,Collection,Map
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 根據類型找到匹配的bean,matchingBeans(key: beanName value: 如果bean已經緩存了實例(例如單例bean會緩存其實例),
// 就是bean的實例,否則就是對應的class對象)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 沒有找到匹配的bean,判斷是不是必需的,不是直接返回null,否則拋出異常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 如果有多個匹配的候選者
if (matchingBeans.size() > 1) {
// 判斷最佳的候選者,也就是尋找最匹配的beanName
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
// 拿到autowiredBeanName對應的value(bean實例或bean實例類型)
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
// 只找到一個符合的bean
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
// 將依賴的beanName添加到autowiredBeanNames中
autowiredBeanNames.add(autowiredBeanName);
}
// 如果需要注入的bean沒有緩存實例,那麼instanceCandidate是一個Class對象,再根據getBean()去獲取對應的實例
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
// 返回最終需要注入的bean實例
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
上面代碼才是真正去獲取需要注入的 bean
,大概分為以下幾個步驟:
-
查看是否有快捷方式獲取注入
bean
是否為空,不為空直接返回。這裡的快捷方式是通過繼承DependencyDescriptor
並重寫resolveShortcut()
來實現。 -
如果參數使用
@Value
註解修飾了,如果獲取到值直接返回。 -
解析
MultipleBean
,這裡的MultipleBean
一般是Array
、Collection
、Map
這種,不為空直接返回。 -
根據類型找到所有匹配的
bean
,matchingBeans
中key
為beanName
,value
的值有兩種情況,如果bean已經緩存了實例(例如單例bean會緩存其實例),就是bean的實例,否則就是對應的class對象)。 -
matchingBeans
為空,判斷需要注入的bean
是否是必須的,如果是拋出異常,否則返回null
。 -
matchingBeans
長度大於1,代表有多個候選者;選擇最佳的候選者,規則是:- 首先查找
primary
屬性為true
的。 - 查找優先級最高的,實現
PriorityOrdered
接口或者標註@Priority
註解的。 - 查找名稱匹配的。
- 首先查找
-
只有一個候選者,直接使用。
-
如果需要注入的
bean
沒有緩存實例,那麼instanceCandidate
是一個Class
對象,再根據getBean()
去獲取對應的實例。 -
最終返回需要注入的
bean
實例。
AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
上面代碼很簡單,無非就是拿到所有註冊的 BeanPostProcessor
,然後遍歷判斷是否是 MeragedBeanDefinitionPostProcessor
類型,是的話進行 BeanDefinition
合併後的方法回調,在這個回調方法內你可以對指定 bean
的 BeanDefinition
做一些修改。
下面我們簡單看一下 MergedBeanDefinitionPostProcessor
接口中的方法:
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
* 對指定bean的BeanDefinition合併後的處理方法回調
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
/**
* 通知已重新設置指定beanName的BeanDefinition,如果實現該方法應該清除受影響的bean的所有元數據
* @since 5.1
*/
default void resetBeanDefinition(String beanName) {
}
}
DefaultSingletonBeanRegistry#addSingletonFactory
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
// 加鎖
synchronized (this.singletonObjects) {
// 如果單例bean緩存中不包含當前beanName
if (!this.singletonObjects.containsKey(beanName)) {
// 將創建實例的ObjectFactory加入到緩存中
this.singletonFactories.put(beanName, singletonFactory);
// 將bean從早起單例bean緩存中移除
this.earlySingletonObjects.remove(beanName);
// 將beanName加入到已經註冊過的單例bean緩存中
this.registeredSingletons.add(beanName);
}
}
}
上面代碼將 ObjectFactory
加入 singletonFactories
緩存中,以下是 singletonFactories
的聲明:
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
下面以一個簡單的AB循環依賴為例,類A中含有屬性類B,而類B中又會含有屬性類A。那麼初始化 beanA 的過程如下圖所示:
Spring 解決循環依賴的方法就在 addSingletonFactory()
和 getBean()
方法中。首先創建 beanA
時,將實例化好的 beanA
封裝成 ObjectFactory
放入 singletonFactories
緩存中,接着進行屬性填充;因為依賴 beanB
所以先去實例化 beanB
,接着 beanB
屬性填充,發現需要 beanA
就調用 getBean()
去獲取 beanA
實例。上篇文章講過 getBean()
會首先判斷緩存中是否有已經創建好的 bean
或者是 beanFactory
,如下代碼所示:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 檢查單例傳中是否存在
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 如果為空,並且當前bean正在創建中,鎖定全局變量進行處理
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 當某些方法需要提前初始化時則會調用addSingletonFactory方法將對應的
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 調用預先設定的getObject(),此時就會返回未填充屬性的beanA
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
因為 beanA
與 beanB
中的 beanA
所表示的屬性地址是一樣的,所以在 beanA
中創建好的屬性填充自然可以通過 beanB
中的 beanA
獲取,這樣就解決了循環依賴的問題。
AbstractAutowireCapableBeanFactory#getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
上面代碼很簡單,就是判斷是否有註冊 InstantiationAwareBeanPostProcessor
的實現,如果有遍歷找到類型是 SmartInstantiationAwareBeanPostProcessor
調用 getEarlyBeanReference()
返回 bean
的實例。
這裡又是一個 Spring 的擴展點,其中我們熟知的 AOP 就是在這裡將 advice
動態織入 bean
中,若沒有則直接返回 bean
,不做任何處理。
AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 給InstantiationAwareBeanPostProcessors最後一次機會在屬性設置前來改變bean
// 例如:可以用來支持屬性注入的類型
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
// 這裡會調用bean實例化後的生命周期回調,返回false會跳過下面的屬性賦值階段
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
// 獲取PropertyValues
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根據名稱自動注入,見下文詳解
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根據類型自動注入,見下文詳解
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否有註冊InstantiationAwareBeanPostProcessors的實現類
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 遍歷並找到InstantiationAwareBeanPostProcessor的實現類,調用處理屬性值的後置處理方法
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
// 如果屬性值的後置處理方法返回null,直接返回,不會進行底下的屬性值應用階段
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
// 屬性填充,見下文詳解
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
上面代碼首先會調用 bean
的實例化後生命周期回調方法,如果返回 false
會跳過下面的屬性賦值階段。下面我們簡單看一下 InstantiationAwareBeanPostProcessors
的接口定義:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* Bean 實例化前調用,返回非 {@code null} IoC 容器不會對 Bean 進行實例化 並且後續的生命周期回調方 * 法不會調用,返回 {@code null} 則進行 IoC 容器對 Bean 的實例化
* 該方法上篇文章分析過
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/**
* Bean 實例化之後,屬性填充之前調用,返回 {@code true} 則進行默認的屬性填充步驟,返回 {@code * false} 會跳過屬性填充階段。
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* Bean 實例化後屬性賦值前調用,PropertyValues 是已經封裝好的設置的屬性值,返回 {@code null} 繼續
* 使用現有屬性,否則會替換 PropertyValues。
* @since 5.1版本新加的和底下的方法一樣
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
/**
* 跟上面方法一樣的功能,只不過是5.1以前版本所使用的
* 返回 {@code null} 會跳過屬性填充階段
*/
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
接着判斷是否是按 名稱 或者 類型 自動注入屬性並填入 newPvs
中,接着調用 bean
屬性填充前的生命周期回調。屬性填充前生命周期回調方法有兩個 postProcessProperties()
和 postProcessPropertyValues()
,第一個是 Spring 5.1 新加的,後面的是老的,已經被標記為過時;首先會調用 postProcessProperties()
如果返回空調用 postProcessPropertyValues()
,否則直接使用返回的 PropertyValues
;postProcessPropertyValues()
如果返回空會直接跳過屬性填充階段,不為空直接使用返回的 PropertyValues
。
AbstractAutowireCapableBeanFactory#autowireByName
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 尋找bw中需要依賴注入的屬性名稱
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍歷需要注入的bean
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
// 將需要注入bean的實例加入到pvs
pvs.add(propertyName, bean);
// 註冊依賴關係,上篇文章有分析過
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
} else {
// 當前需要注入的bean,拋出異常
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName + "' by name: no matching bean found");
}
}
}
}
AbstractAutowireCapableBeanFactory#autowireByType
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 尋找bw中需要依賴注入的屬性名稱
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
// 根據類型注入永遠不要注入Object類型,你細細地品一下
if (Object.class != pd.getPropertyType()) {
// 獲取屬性的可寫方法,一般是set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 這個方法上面分析過,這裡不再贅述,最後返回符合條件需要注入的bean實例
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
// 需要注入的bean實例不為空,加入到pvc
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
// 註冊依賴關係,上篇文章分析過方法
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
AbstractAutowireCapableBeanFactory#applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 屬性為空,直接返回
if (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 = (MutablePropertyValues) pvs;
// 快捷方式,如果屬性已經轉換過,直接填充進BeanWrapper
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
// 屬性沒有轉換過,獲取屬性列表
original = mpvs.getPropertyValueList();
} else {
// 獲取屬性列表
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 獲取對應的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
// 創建深拷貝,解決引用的問題
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
// 遍歷屬性,將屬性轉換為對應的類型
for (PropertyValue pv : original) {
// 如果pv類型轉換過,直接添加進deepCopy
if (pv.isConverted()) {
deepCopy.add(pv);
} else {
// 進行轉換
// 拿到pv原始屬性名和屬性值
String propertyName = pv.getName();
Object originalValue = pv.getValue();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
// 進行類型轉換
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);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
// 在合併的BeanDefinition中存儲轉換後的值,以避免為每個創建的bean實例重新轉換
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();
}
// Set our (possibly massaged) deep copy.
try {
// 填充bean屬性值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
上面代碼主要就是進行屬性的類型轉換,最後填充 bean
的屬性值,這裡一般就是利用反射使用 set()
去給屬性賦值。
AbstractAutoCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// BeanAware的接口回調,見下文詳解
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor的postProcessBeforeInitialization()回調,也就是bean初始化前的回調
// 在 ApplicationContextAwareProcessor實現的postProcessBeforeInitialization方法中會執行
// ApplicationContext Aware的接口回調。
// InitDestoryAnnotationBeanPostProcessor的postProcessBeforeInitialization()中會執行
// 標註了@PostConstruct註解的方法。
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 調用bean的自定義初始化方法,如afterPropertiesSet,XML中的init屬性指定的方法等
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()回調,也就是bean初始化後的回調
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAutowireCapableBeanFactory#invokeAwareMethods
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
// BeanNameAware接口方法回調
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// BeanClassLoaderAware接口方法回調
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
// BeanFactoryAware接口方法回調
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)
bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
實現這些 Aware
接口的 bean
的被初始化之前,可以取得一些相對應的資源,比如 beanName
、beanFactory
等。
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
// 遍歷所有註冊的BeanPostProcessor實現類,調用postProcessBeforeInitialization方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 在bean初始化方法執行前,調用postProcessBeforeInitialization方法
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
AbstractAutowireCapableBeanFactory#invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// bean是否實現InitializingBean接口
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
// 調用afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
}
// 調用自定義的init方法,例如XML中init-method屬性設置的方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
綜合上面的代碼來看,bean
初始化階段流程主要如下:
@PostConstruct
註解修飾的方法,前提是註解驅動- 實現
InitializingBean
接口的afterPropertySet()
- 自定義初始化方法,例如 XML 中的
init-method
屬性設置的方法
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 遍歷所有註冊的BeanPostProcessor實現類,調用postProcessAfterInitialization方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 在bean初始化方法執行後,調用postProcessBeforeInitialization方法
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
下面我們簡單看一下 BeanPostProcessor
接口,如下:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
BeanPostProcessor
接口比較簡單,就提供了兩個接口回調,一個初始化前,一個初始化後。但是其它的 PostProcessor
大部門以此為基礎,繼承自 BeanPostProcessor
。
AbstractBeanFactory#registerDisposableBeanIfNecessary
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
// bean的作用域不是原型 && bean需要在關閉時銷毀
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// 單例模式下註冊用於銷毀的bean到disposableBeans緩存,執行給定bean的所有銷毀工作:
// DestructionAwareBeanPostProcessors,DisposableBean接口,自定義銷毀方法
// DisposableBeanAdapter:使用DisposableBeanAdapter來封裝用於銷毀的bean
// 見下文詳解
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
// bean是自定義作用域
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
// 註冊一個回調,在銷毀時執行,執行時機自己去管理,Spring不會幫忙調用
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
DisposableBeanAdapter構造函數
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = beanName;
// 判斷bean是否要調用DisposableBean的destroy方法
this.invokeDisposableBean =
(this.bean instanceof DisposableBean &&
!beanDefinition.isExternallyManagedDestroyMethod("destroy"));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
// 獲取自定義的destroy方法名,賦值給destroyMethodName
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
// 獲取自定義的destroy方法名賦值給destroyMethodName
this.destroyMethodName = destroyMethodName;
Method destroyMethod = determineDestroyMethod(destroyMethodName);
// 如果判定後的destroyMethod為空,拋出異常
if (destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
// 如果判定後的destroyMethod不為空
else {
// 獲取destroyMethod的方法參數
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
// 參數長度大於1拋出異常,自定義的destroy方法最多只允許有一個boolean參數
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
// 參數長度等於1 && 不是boolean類型,拋出異常
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
}
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
}
this.destroyMethod = destroyMethod;
}
// 查找DestructionAwareBeanPostProcessors,並賦值給this.beanPostProcessors,見下文詳解
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
DisposableBeanAdapter#filterPostProcessors
private List<DestructionAwareBeanPostProcessor> filterPostProcessors(List<BeanPostProcessor> processors, Object bean) {
List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
// processors長度不為空
if (!CollectionUtils.isEmpty(processors)) {
// 遍歷processors
for (BeanPostProcessor processor : processors) {
// 如果processor的類型是DestructionAwareBeanPostProcessor
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
// 如果bean實際需要通過此後置處理器進行銷毀,則添加到filteredPostProcessors
if (dabpp.requiresDestruction(bean)) {
filteredPostProcessors.add(dabpp);
}
}
}
}
return filteredPostProcessors;
}
上面的代碼主要就是判斷如果 BeanPostProcessor
是 DestructionAwareBeanPostProcessor
並且 requiresDestruction()
返回 true
代表需要通過後置處理器進行銷毀實例,將該 BeanPostProcessor
添加到 filteredPostProcessors
中。
下面我們簡單看一下 DestructionAwareBeanPostProcessor
接口的定義:
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
/**
* bean 銷毀前階段生命周期回調方法
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
/**
* bean 實例是否要由此後置處理器進行實例的銷毀
*/
default boolean requiresDestruction(Object bean) {
return true;
}
}
可以看到其也是繼承於 BeanPostProcessor
,主要提供兩個方法一個是 bean
銷毀前的生命周期方法回調,另一個是判定 bean
實例是否要由此後置處理器進行實例的銷毀。
DefaultListableBeanFactory#destroySingletons
因為基本上 BeanFactory
就只會使用 DefaultListableBeanFactory
這一個最終實現,所以我們這裡分析一下這裡的銷毀單例 bean
的方法。
public void destroySingletons() {
// 調用父類的銷毀所有單例bean方法
super.destroySingletons();
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
// 清除所有bean類型的緩存
clearByTypeCache();
}
// DefaultSingletonBeanRegistry.java
public void destroySingletons() {
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
// 獲取所有需要銷毀的bean
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
// 根據註冊順序,倒着遍歷,銷毀bean
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
// 從緩存中清除所有單例實例
clearSingletonCache();
}
// DefaultSingletonBeanRegistry.java
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
// 從緩存中清除所有當前beanName單例實例
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
// 加鎖,從disposableBeans中將當前bean移除
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
// 銷毀bean
destroyBean(beanName, disposableBean);
}
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// Trigger destruction of dependent beans first...
Set<String> dependencies;
// 加鎖,從dependentBeanMap中移除當前bean
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isTraceEnabled()) {
logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
// dependencies不為空,說明,當前bean有其它依賴的bean,遍歷去銷毀
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
}
// Actually destroy the bean now...
// bean不為空,調用destroy方法真正的開始進行銷毀
if (bean != null) {
try {
bean.destroy();
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
}
}
}
// Trigger destruction of contained beans...
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);
}
}
// Remove destroyed bean from other beans' dependencies.
synchronized (this.dependentBeanMap) {
for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Set<String>> entry = it.next();
Set<String> dependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
}
// Remove destroyed bean's prepared dependency information.
this.dependenciesForBeanMap.remove(beanName);
}
DisposableBeanAdapter#destroy
public void destroy() {
// 如果beanPostProcessors不為空
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
// 遍歷beanPostProcessors調用postProcessBeforeDestruction()
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
// 調用實現了DisposableBean的destroy()
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
// 調用自定義的destroy方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) { invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
總得來說上面方法主要分為三步:
-
回調實現了
DestructionAwareBeanPostProcessor
接口的postProcessBeforeDestruction
方法,InitDestoryAnnotationBeanPostProcessor
的postProcessBeforeDestruction()
中會執行標註了@PreDestory
註解的方法。 -
調用實現了
DisposableBean
接口的destroy()
。 -
調用自定義實現的
destroyMethod
,例如 XML 中的destory
屬性指定的方法
總結
本文主要介紹了 createBean()
流程,我們可以重新梳理一下思路:
- 進行
bean
的實例化前方法回調,如果返回非空,跳過後面步驟 - 創建
bean
的實例,如果是構造函數注入會選擇最適合的構造函數進行參數自動注入,否則調用默認的無參構造進行實例化bean
。 - 如果
bean
允許提前曝光,將beanName
對應的ObjectFactory
放入singletonFactories
緩存中。 bean
的屬性賦值階段,首先調用bean
實例化後方法回調,返回false
會跳過後面的賦值階段;判斷是否是按照名稱或者類型自動注入,是則進行屬性自動注入。接着調用處理屬性值的後置處理方法,首先調用Spring5.1版本新加的方法,如果返回的屬性為空,再調用以前版本的方法,如果為空,直接返回,沒必要再走後面的實際賦值階段。bean
的初始化階段,首先是調用可以獲取相應資源的一些Aware
接口;然後調用bean
初始化前回調方法 (InitDestroyAnnotationBeanPostProcessor
的postProcessBeforeInitialization()
中會執行
標註了@PostConstruct
註解的方法),接着調用重寫的afterPropertiesSet()
和自定義的初始化方法;最後進行bean
初始化後回調方法。- 註冊銷毀
bean
的方法。 - 最後返回
bean
的實例。
最後,我模仿 Spring 寫了一個精簡版,代碼會持續更新,現在是 0.0.3
版本。地址://github.com/leisurexi/tiny-spring。訪問新博客地址,觀看效果更佳 //leisurexi.github.io/
參考
- 《Spring 源碼深度解析》—— 郝佳