bean 的載入(五)
前一篇文章主要講解了建立 bean 中的 createBeanInstance 方法和例項化過程。本文繼續講解關於 bean 的載入過程中屬性注入和註冊 DisposableBean。
屬性注入 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 {
//沒有可填充的屬性
return;
}
}
//給InstantiationAwareBeanPostProcessors最後一個機會在屬性設定前改變bean
// 具體通過呼叫ibp.postProcessAfterInstantiation方法,如果呼叫返回false,表示不必繼續進行依賴注入,直接返回
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)) {
//返回值為是否繼續填充bean
continueWithPropertyPopulation = false;
break;
}
}
}
}
//如果後處理器發出停止填充命令則終止後續的執行
if (!continueWithPropertyPopulation) {
return;
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 根據bean的依賴注入方式:即是否標註有 @Autowired 註解或 autowire=“byType/byName” 的標籤
// 會遍歷bean中的屬性,根據型別或名稱來完成相應的注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//根據名稱自動注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
// 程式碼(1)
autowireByName(beanName, mbd, bw, newPvs);
}
//根據型別自動注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// 程式碼(2)
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 容器是否註冊了InstantiationAwareBeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否進行依賴檢查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
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);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
// 檢查是否滿足相關依賴關係,對應的depends-on屬性,3.0後已棄用
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 如果pvs不為空,將pvs上所有的屬性填充到BeanWrapper對應的Bean例項中
if (pvs != null) {
//程式碼(3)
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
在 populateBean 方法中處理流程大致如下:
- InstantiationAwareBeanPostProcessor 處理器中的 postProcessAfterInstantiation 方法的應用,可以控制程式是否繼續進行屬性填充
- 根據注入型別(byType/byName),提取依賴的 bean,並統一存入 PropertyValues 中
- 應用 InstantiationAwareBeanPostProcessor 處理器的 postProcessPropertyValues 方法,對屬性獲取完畢填充前對屬性的再次處理,典型應用就是 RequiredAnnotationBeanPostProcessor 類中對屬性的驗證
- 將所有 PropertyValues 中的屬性填充至 BeanWrapper 中
我們先分析一下程式碼(1)看一下 byName 是如何實現的。
autowireByName
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//尋找bw中需要依賴注入的屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
//檢查快取bean中是否存在當前bean
if (containsBean(propertyName)) {
//遞迴初始化相關的bean. 程式碼(1)
Object bean = getBean(propertyName);
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 {
// 找不到則不處理
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
byName 的處理邏輯很簡單,獲取需要注入的 bean,然後遞迴呼叫 getBean
獲取 bean
進行注入。
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);
//不要嘗試按型別為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 = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//解析指定beanName的屬性所匹配的值,並把解析到的屬性名稱儲存在autowiredBeanNames中,當屬性存在多個封裝bean時
//比如: @Autowired private List<A> aList; 就會找到所有匹配A型別的bean並將其注入
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
// 新增到待注入的bean列表中
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);
}
}
}
- 獲取型別轉換器,如果沒有,預設為 bw
- 獲取需要注入的屬性
- 對所有屬性進行遍歷並開始注入, 首先排除 Object.class 型別,呼叫 resolveDependency() 方法進行校驗獲取對應的 bean
- 放入 pvs 裡面,並呼叫 registerDependentBean() 方法註冊對應的依賴和被依賴關係
autowiredBeanNames 屬性主要處理集合型別的注入方式,比如@autowired private List<A> tests
,如果是非集合型別則該屬性並無用處。
我們看一下重點是如何尋找型別匹配的。進入 resolveDependency 方法中。
DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
//Optional類注入的特殊處理
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
//ObjectFactory/ObjectProvider類注入的特殊處理
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
//javaxInjectProviderClass類注入的特殊處理
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//通用處理邏輯
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//從descriptor中獲取屬性型別
Class<?> type = descriptor.getDependencyType();
//用於支援註解@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()));
}
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//查詢符合注入屬性型別的bean ,這裡過濾了 @Bean(autowireCandidate = false)和不符合@Qualifier("beanName")的bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
//為空說明找不到該注入型別的bean,如果注入的屬性又是必須的,則丟擲異常NoSuchBeanDefinitionException
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//查詢到多個符合注入屬性型別的bean
if (matchingBeans.size() > 1) {
// 再次過濾找到最優的beanName,進而獲取最優的用來建立例項的候選者instanceCandidate
// 這裡挑選@primary、@Priority等優先順序高的bean
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
// 找不到最優的beanName,注入的屬性又是必須的,則拋NoUniqueBeanDefinitionException異常
// 注入的屬性非必須,未過濾前就有多個注入屬性型別的bean,如果注入的屬性不是集合,也拋異常
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
// 根據beanName獲取最優的用來建立屬性例項的候選者instanceCandidate
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
//確定只有一個匹配項
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
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());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
該方法在尋找型別的匹配執行順序時,首先嚐試使用解析器進行解析,如果沒有成功解析,那麼可能是使用預設的解析器沒有做任何處理,或者使用了自定義解析器,但是對於集合等型別來說並不在解析範圍內,所以再次對不同型別進行不同情況的處理。
applyPropertyValues
執行到這裡後,已經完成了對所有注入屬性的獲取,但是獲取到的屬性都是 PropertyValues 形式,還沒有應用到已經例項化的 bean 中,這一工作都是在 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;
//如果mpvs中的值已經被轉換為對應的型別那麼可以直接設定到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 {
//如果pvs並不是使用MutablePropertyValues封裝的型別,那麼直接使用原始的屬性獲取方法
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) {
if (pv.isConverted()) {
deepCopy.add(pv);
} else {
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.
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 {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
} catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
初始化 bean
我們知道在配置 bean 的時候有一個init-method
的屬性,這個屬性就是在 bean 例項化前呼叫所指定的方法,根據業務需求進行相應的例項化,我們現在還是回到 doCreateBean 中。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
//程式碼(1) 啟用 Aware 方法
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
//對特殊的bean處理,Aware / BeanClassLoaderAware / BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 呼叫bean後處理器的方法
// BeanPostProcessor 提供的方法,在bean初始化前呼叫,這時的 bean已完成了例項化和屬性填充注入工作
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//啟用使用者自定義的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()) {
// 呼叫bean後處理器的方法
// BeanPostProcessor 提供的方法,在bean初始化後呼叫,這時候的bean 已經建立完成了
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
雖然該方法主要目的是執行我們設定的初始化方法的呼叫,但是除此之外還有其他必要的工作。
1.啟用Aware方法
在瞭解原理前,我們先了解一下什麼是 Aware,Spring
中提供了一些 Aware 相關介面,比如 BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware 等,比如實現了 BeanFactoryAware 的介面的 bean 在初始化後,Spring 容器會注入 BeanFactory 的例項,實現了 ApplicationContextAware 介面的 bean 會被注入到 ApplicationContext 的例項等。
我們先了解一下 Aware 的使用。
- 定義一個普通 bean
/**
* @author 神祕傑克
* 公眾號: Java菜鳥程式設計師
* @date 2022/6/8
* @Description
*/
public class Hello {
public void say(){
System.out.println("hello");
}
}
- 定義 BeanFactoryAware 型別的 bean
/**
* @author 神祕傑克
* 公眾號: Java菜鳥程式設計師
* @date 2022/6/8
* @Description
*/
public class AwareTest implements BeanFactoryAware {
private BeanFactory beanFactory;
//宣告bean的時候Spring會自動注入BeanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void testAware(){
//通過beanFactory獲取hello bean
final Hello hello = (Hello) beanFactory.getBean("hello");
hello.say();
}
}
- 註冊 bean
<bean id="hello" class="cn.jack.Hello"/>
<bean id="awareTest" class="cn.jack.AwareTest"/>
- 測試
public class Test {
public static void main(String[] args) {
final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
final AwareTest awareTest = (AwareTest) applicationContext.getBean("awareTest");
awareTest.testAware();
}
}
- 執行結果
hello
按照上面的方式我們可以獲取到 Spring 中的 BeanFactory,並可以根據 BeanFactory 獲取所有 bean,以及進行相關設定,其他 Aware 都大同小異。
具體我們看一下程式碼(1)呼叫的方法就可以一下看明白了。非常簡單。
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) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
2. 處理器的應用
BeanPostProcessor 是 Spring 中開放式架構中必不可少的一個亮點,給了使用者充足的許可權去更改或者擴充套件 Spring,除了 BeanPostProcessor 外還有很多其他的 PostProcessor,當然大部分都是以此為基礎,繼承自 BeanPostProcessor。
在呼叫我們自定義初始化方法前後會分別呼叫 BeanPostProcessor 的postProcessBeforeInitialization
和postProcessAfterInitialization
方法,使得我們可以根據業務需求進行響應的處理。
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 獲取所有實現了 BeanPostProcessors 介面的類,進行遍歷
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 核心方法:postProcessBeforeInitialization
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 獲取所有實現了 BeanPostProcessors 介面的類,進行遍歷
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 核心方法:postProcessAfterInitialization
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
3. 啟用自定義的init方法
初始化方法除了使用 init-method 外,還有自定義的 bean 實現 InitializingBean 介面,實現 afterPropertiesSet 方法實現自己的初始化業務邏輯。
當然,這兩種都是在初始化 bean 的時候執行,實行順序是 afterPropertiesSet 先執行,而 init-method 後執行。
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//先檢查是否為isInitializingBean,如果是的話先呼叫afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
// 呼叫 afterPropertiesSet 方法
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
// 從RootBeanDefinition 中獲取initMethod 方法名稱
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 呼叫initMethod 方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
需要注意的是,在使用了@PostConstruct 註解和實現了 InitializingBean 介面和 init-method 的時候。
執行順序為 PostConstruct -> InitializingBean -> init-method
註冊 DisposableBean
在 doCreateBean 中還有最後一步,就是註冊 bean 到 disposableBeans,以便在銷燬 bean 的時候 可以執行指定的相關業務。
除了我們熟知的 destroy-method 方法外,我們還可以註冊後處理器DestructionAwareBeanPostProcessor
來統一 bean 的銷燬方法。
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
//如果為單例
if (mbd.isSingleton()) {
/**
* 註冊一個DisposableBean的實現為以下三種給出的bean做所有的銷燬工作:
* DestructionAwareBeanPostProcessor,DisposableBean,自定義destroy方法
*/
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
//自定義scope的處理
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
至此,Spring bean 的載入流程就先告一段落。