在上篇文章中,咱们详细分析了
doCreateBean()
中的第5步:属性填充,本文接着分析doCreateBean()
的第6步——初始化 bean 实例对象java
本文转自公众号:芋道源码编程
首先回顾下CreateBean
的主流程:数组
createBeanInstance()
实例化 beanSpring在对Bean进行属性填充以后,会对Bean进行初始化,代码以下:缓存
//AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//JDK的安全机制验证权限
if (System.getSecurityManager() != null) {
// <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// <2> 后置处理器,before
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// <3> 激活用户自定义的 init 方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// <2> 后置处理器,after
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
复制代码
初始化 bean 的方法其实就是三个步骤的处理,而这三个步骤主要仍是根据用户设定的来进行初始化,这三个过程为:安全
<1> 激活 Aware 方法。app
<2> 后置处理器。ide
<3> 自定义的 init 方法。post
Aware ,英文翻译是意识到的,感知的。Spring 提供了诸多 Aware 接口,用于辅助 Spring Bean 以编程的方式调用 Spring 容器,经过实现这些接口,能够加强 Spring Bean 的功能。学习
Spring 提供了以下系列的 Aware 接口:spa
LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
BeanClassLoaderAware:加载Spring Bean的类加载器
BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
ResourceLoaderAware:底层访问资源的加载器
BeanFactoryAware:声明BeanFactory
PortletConfigAware:PortletConfig
PortletContextAware:PortletContext
ServletConfigAware:ServletConfig
ServletContextAware:ServletContext
MessageSourceAware:国际化
ApplicationEventPublisherAware:应用事件
NotificationPublisherAware:JMX通知
BeanNameAware:声明Spring Bean的名字
Aware比较复杂,后面会专门学习一下这块内容,这里就很少说了。
BeanPostProcessor 在前面介绍 bean 加载的过程曾屡次遇到,
它的做用是:
若是咱们想要在 Spring 容器完成 Bean 的实例化,配置和其余的初始化后添加一些本身的逻辑处理,那么请使用该接口,这个接口给与了用户充足的权限去更改或者扩展 Spring,是咱们对 Spring 进行扩展和加强处理一个必不可少的接口。
applyBeanPostProcessorsBeforeInitialization()
方法,代码以下:
// AbstractAutowireCapableBeanFactory.java
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
// 遍历 BeanPostProcessor 数组
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 处理
Object current = processor.postProcessBeforeInitialization(result, beanName);
// 返回空,则返回 result
if (current == null) {
return result;
}
// 修改 result
result = current;
}
return result;
}
复制代码
applyBeanPostProcessorsAfterInitialization()
方法,代码以下:
// AbstractAutowireCapableBeanFactory.java
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
// 遍历 BeanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 处理
Object current = processor.postProcessAfterInitialization(result, beanName);
// 返回空,则返回 result
if (current == null) {
return result;
}
// 修改 result
result = current;
}
return result;
}
复制代码
其逻辑就是经过 getBeanPostProcessors() 方法,获取定义的 BeanPostProcessor ,而后分别调用其 postProcessBeforeInitialization() 和 postProcessAfterInitialization() 方法,进行自定义的业务处理。
在xml中有一个< bean >标签的配置, init-method
方法,是可让咱们在Bean初始化的时候,先执行咱们自定义的一些逻辑。
其实就是在这里被触发的,代码以下:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
// 首先会检查是不是 InitializingBean ,若是是的话须要调用 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 + "'");
}
if (System.getSecurityManager() != null) { // 安全模式
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
// <1> 属性初始化的处理
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
// <1> 属性初始化的处理
((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);
}
}
}
复制代码
首先,检查是否为 InitializingBean 。若是是的话,须要执行 afterPropertiesSet()
方法,由于咱们除了可使用 init-method 来自定初始化方法外,还能够实现 InitializingBean 接口。接口仅有一个 afterPropertiesSet() 方法。 二者的执行前后顺序是先 <1> 的 #afterPropertiesSet() 方法,后 <2> 的 init-method 对应的方法。