Spring三种初始化bean的方式及其顺序

Spring中有三种初始化Bean的方式:

  • 对初始化方法添加注解 @PostConstruct
  • 实现 InitializingBean 接口
  • 实现 SmartInitializingSingleton 接口

首先要测试三种初始化的执行顺序,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
public class InitTest implements InitializingBean, SmartInitializingSingleton {

@PostConstruct
public void postConstruct() {
System.out.println("@PostConstruct");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}

@Override
public void afterSingletonsInstantiated() {
System.out.println("afterSingletonsInstantiated");
}
}

image.png

执行顺序显而易见,接下开是要说下这三种方式都是在什么地方进行执行的。

初始化 bean 的部分代码在 AbstractAutowireCapableBeanFactory.java 中的 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
37
38
39
40
41
42
43
44
45
46
47
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 {
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// ① 为这个 bean 调用所有的 BeanPostProcessor 处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
// ② 为每个 bean 调用初始化方法
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()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 拿到所有的 BeanPostProcessor 接口,并依次调用
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

@PostConstruct

① 那个位置上,会取出所有的 BeanPostProcessor 接口,并依次调用,其中有个后处理器为 CommonAnnotationBeanPostProcessor,它就是处理 PostConstruct 的关键,它的构造方法中 含有 PostConstruct 注解,声明拥有这个注解的方法是初始化方法。

1
2
3
4
5
6
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}

它还继承了 InitDestroyAnnotationBeanPostProcessor,该父类实现了 BeanPostProcessor 的接口,它本身未实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// metadata 中包是含有 PostConstruct 注解的方法,具体寻找过程不作说明
InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 调用含有 PostConstruct 注解的方法
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}

InitializingBean

② 这个位置上会调用 bean 的 InitializingBean 方法,这个方法会判断这个 bean 是否实现了 InitializingBean 接口,如果实现了,则调用其 afterPropertiesSet() 方法。

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
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {

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>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((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)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}

SmartInitializingSingleton