概述
在Spring4.3.x 容器中bean的創建過程(1)——走進初始化bean的主要戰場一篇中我們找到了初始化bean的主要場所在AbstractAutowireCapableBeanFactory類中的doCreateBean方法中,在這個方法中首先調用createBeanInstance方法創建bean的實例;然後調用populateBean方法設置bean的屬性;接着調用initializeBean方法執行Bean後處理器和InitializingBean對象的afterPropertiesSet方法以及init-method方法;最後調用registerDisposableBeanIfNecessary方法註冊bean的銷燬方法。它的每一步都比較繁瑣,所以我把他們分開來探討。在 Spring4.3.x 容器中bean的創建過程(2)——實例化Bean一篇中,已經探討了第一步實例化bean。在 Spring4.3.x 容器中bean的創建過程(3)—— 初始化bean的屬性值 中探討了通過BeanWrapper對象設置bean的屬性。這一篇則探討最後一步——執行初始化方法並結束bean的創建。
執行bean的初始化方法
AbstractAutowireCapableBeanFactory類中的doCreateBean方法調用它的initializeBean方法來執行與bean初始化相關的各種初始化方法,initializeBean方法的源碼如下。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 首先執行Aware接口的方法
// 這裏涉及的Aware接口有BeanFactoryAware、BeanClassLoaderAware和BeanNameAware
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
} else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 執行bean後處理器的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 執行實現自InitializingBean接口的afterPropertiesSet()方法
// 執行bean的init-method方法
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後處理器的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
如果bean實現了BeanFactoryAware、BeanClassLoaderAware或者BeanNameAware接口,initializeBean方法首先執行這些接口相應的方法,以確保後面的操作能夠拿到相應的對象,比如BeanFactory對象。接下來在執行bean的自身的初始化方法之前,則會執行bean後處理器的postProcessBeforeInitialization方法;在執行bean的自身的初始化方法之後,會執行bean後處理器的postProcessAfterInitialization方法。下面我們分別看看這4個方面的源碼。
(1)執行Aware接口的方法
initializeBean方法調用AbstractAutowireCapableBeanFactory類的invokeAwareMethods方法完成這向任務,源碼如下。
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);
}
}
}
在invokeAwareMethods方法中,我們只看到BeanFactoryAware、BeanClassLoaderAware和BeanNameAware三個接口的執行,Spring中還有其他Aware接口(比如ApplicationContextAware、ResourceLoaderAware、EnvironmentAware等)沒有得到執行。在Spring中,其他Aware接口在bean後處理器中執行,比如ApplicationContextAware、ResourceLoaderAware和EnvironmentAware會被ApplicationContextAwareProcessor後處理器處理,這個ApplicationContextAwareProcessor會在bean工廠創建後被添加到容器中。
(2)執行bean後處理器的postProcessBeforeInitialization方法
initializeBean方法調用AbstractAutowireCapableBeanFactory類的applyBeanPostProcessorsBeforeInitialization方法來發起post方法的執行,源碼如下。
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
在applyBeanPostProcessorsBeforeInitialization方法中,只要post方法返回結果爲null,則終止其他bean後處理的執行。在這裏我們看看ApplicationContextAwareProcessor後處理器的postProcessBeforeInitialization方法源碼,如下。
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
} else {
// 執行Aware接口
invokeAwareInterfaces(bean);
}
return bean;
}
/**執行Aware接口**/
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
(3)執行bean的初始化方法
initializeBean方法調用AbstractAutowireCapableBeanFactory類的invokeInitMethods方法來執行bean的初始化方法,源碼如下。
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
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(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
從invokeInitMethods方法中,首先執行InitializingBean接口的afterPropertiesSet方法,然後調用invokeCustomInitMethod方法執行自定義的初始化方法。下面是invokeCustomInitMethod方法的源碼。
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
String initMethodName = mbd.getInitMethodName();
// 檢查是否不在乎初始化方法是否是public的
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
} else {
if (logger.isDebugEnabled()) {
logger.debug("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isDebugEnabled()) {
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
// 執行初始化操作
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
ReflectionUtils.makeAccessible(initMethod);
return null;
}
});
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
initMethod.invoke(bean);
return null;
}
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
} else {
try {
ReflectionUtils.makeAccessible(initMethod);
initMethod.invoke(bean);
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
invokeCustomInitMethod方法的作用是,根據方法名稱獲取自定義的初始化方法,然後執行bean初始化方法。
(4)執行bean後處理器的postProcessAfterInitialization方法
initializeBean方法調用AbstractAutowireCapableBeanFactory類的applyBeanPostProcessorsAfterInitialization方法來發起post方法的執行,源碼如下。
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
在applyBeanPostProcessorsAfterInitialization方法中,只要post方法返回結果爲null,則終止其他bean後處理的執行。
總結
在執行bean完成屬性設置後執行初始化方法的過程中,Spring對bean的初始化操作提供了提供瞭如下擴展點。
(1)Spring提供了各種XxxAware接口,以在初始化的時候向bean注入當前容器擁有的Xxx對象,比如BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、EnvironmentAware等。
(2)Spring提供了BeanPostProcessor接口,可以在執行bean自身的初始化方法前後執行相應的post方法。
(3)Spring提供了InitializingBean接口,可以在bean中實現這個接口的afterPropertiesSet()方法作爲初始化方法。
(4)在xml文件中配置init-method屬性或者在java代碼中使用@PostConstruct指定初始化方法。