一、介紹
初始化bean的動作是在創建bean和給bean填充屬性之後,目的是爲了調用用戶自定義的初始化方法。期間還涉及到Aware接口和BeanPostProcessor的處理,處理流程如下:
二、bean加載流程
- 獲取用戶傳入name對應的beanName
- 嘗試從緩存中獲取bean實例
- 緩存中不存在,加載bean實例
3.1. 檢查循環依賴
3.2 處理parentBeanFactory
3.3 處理依賴的bean(dependsOn)
3.4 三種bean實例的創建
3.4.1 單例bean的創建
3.4.1.1 獲取單例bean,getSingleton()方法
3.4.1.2 準備創建bean,createBean()方法
3.4.1.3 創建bean,doCreateBean()方法
3.4.1.3.1 創建BeanWrapper
3.4.1.3.2 記錄bean的Object-Factory
3.4.1.3.3 屬性填充
3.4.1.3.3 初始化bean(本章解析)
3.4.2 原型bean的創建
3.4.3 根據scope策略創建bean - 從bean實例中獲取真正的對象
- 轉換對象類型
- 返回對象實例
三、主要方法
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean:初始化bean的整體流程
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods:調用具體Aware接口的對應方法
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods:調用用戶自定義的初始化方法
四、源碼分析
1. 初始化bean流程
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 {
// 1. 調用Aware類型bean的對應方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 2. 初始化前,應用後處理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 3. 激活用戶自定義的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()) {
// 4. 初始化後,應用後處理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
從代碼中可以看到,初始化bean不僅僅是調用用戶自定義的初始化方法。而是經歷了以下四個步驟:
- 如果bean是Aware類型,則調用具體Aware的對應方法
- 調用BeanPostProcessor的postProcessBeforeInitialization方法
- 調用bean的初始化方法
- 調用BeanPostProcessor的postProcessAfterInitialization方法
2. 給Aware類型的bean設置資源
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);
}
}
}
如果該bean實現了某種Aware接口,初始化的時候spring就會調用該接口的特定方法,來給bean傳遞某種類型的值。目前一共有三種Aware接口:BeanNameAware(獲取bean名稱)、BeanClassLoaderAware(獲取類加載器)、BeanFactoryAware(獲取bean工廠)。
3. 調用bean的初始化方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 1. 如果是InitializingBean類型的bean,調用bean的afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("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 {
// 調用bean的afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 2. 調用用戶自定義的初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
如果bean實現了InitializingBean接口,則先調用afterPropertiesSet方法;然後調用用戶自定義的初始化方法。指定初始化方法的方式如下
<bean id="personInit" class="com.kaka.spring.pojo.Person" init-method="testInitMethod" />