二十五、创建Bean之初始化Bean

创建Bean之初始化Bean

一个 bean 经历了 createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) 方法,被创建出来,然后又经过了一番属性注入,依赖处理,接下来执行最后一步就是初始化,即执行initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法,这也是doCreateBean(...) 方法的中最后一步:初始化 bean 对象。

initializeBean()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// AbstractAutowireCapableBeanFactory.java

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) { // 安全模式
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
// <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
// <2> 后置处理器,before
Object wrappedBean = bean;
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 方法。
  • <3> 后置处理器的应用。
  • <2> 激活自定义的 init 方法。
激活 Aware 方法

Spring 提供了诸多 Aware 接口,用于辅助 Spring Bean 以编程的方式调用 Spring 容器,通过实现这些接口,可以增强 Spring Bean 的功能。

Spring 提供了如下系列的 Aware 接口:

  • 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的名字

invokeAwareMethods()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// AbstractAutowireCapableBeanFactory.java

//主要是处理 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 。
private void invokeAwareMethods(String beanName, 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);
}
}
}
后置处理器的应用

BeanPostProcessor 在前面介绍 bean 加载的过程已多次遇到。

BeanPostProcessor 的作用是:如果我们想要在 Spring 容器完成 Bean 的实例化,配置和其他的初始化后添加一些自己的逻辑处理,那么请使用该接口,这个接口给与了用户充足的权限去更改或者扩展 Spring,是我们对 Spring 进行扩展和增强处理一个必不可少的接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 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;
}

@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 = current;
}
return result;
}

其实,逻辑就是通过 getBeanPostProcessors() 方法,获取定义的 BeanPostProcessor ,然后分别调用其 postProcessBeforeInitialization(...)postProcessAfterInitialization(...) 方法,进行自定义的业务处理。

激活自定义的 init 方法

spring配置文件中的<bean>标签,有一个属性init-method,该属性的方法值就是通过以下方法执行的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
protected void invokeInitMethods(String beanName, 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 对应的方法。

二十五、创建Bean之初始化Bean
http://www.muzili.ren/2022/06/11/创建Bean之初始化Bean/
作者
jievhaha
发布于
2022年6月11日
许可协议