构造器、init-method、@PostConstruct、afterPropertiesSet 都可以做初始化用,但到底执行顺序是怎么样的呢?(调式Spring版本为4.3.12.RELEASE)
示例
先写个例子,看一下效果
TestInit.java
public class TestInit implements InitializingBean {
public TestInit() {
System.out.println("constructor");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
@PostConstruct
public void postConstruct(){
System.out.println("postConstruct");
}
public void initMethod() {
System.out.println("initMethod");
}
}
InitDemo.java
@Component
public class InitClass {
@Bean(initMethod = "initMethod")
public TestInit initTest(){
return new TestInit();
}
}
执行结果:
constructor
postConstruct
afterPropertiesSet
initMethod
可以看到执行顺序为 constructor > postConstruct > afterPropertiesSet > initMethod
源码分析
-
构造器,是属于java类的,在实例化的时候就会被调用,所以毋庸置疑
-
postConstruct > afterPropertiesSet > initMethod 这三个顺序是如何决定的?
我们分别在TestInit.java 对应的3个方法体中打一个断点,跑起来
断点首先到了postConstruct中,看下调用栈
往下走,跳过该断点,到了afterPropertiesSet中,调用栈是这样的
继续往下走,跳过该断点,到了initMethod中,同样看调用栈
有没有发现,都是从initializeBean开始的,看下这个地方的代码
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
//是否启用了安全管理器
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
//执行aware扩展点
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
//Synthetic是由编译器生成的类型
if (mbd == null || !mbd.isSynthetic()) {
//如果实现了BeanPostProcessor接口 这里会执行postProcessBeforeInitialization方法
//@PostConstruct注解是在CommonAnnotationBeanPostProcessor类中初始化的
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//这里就开始执行initMethod 和 afterPropertiesSet方法
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;
}
从这里就会看到@PostConstruct先执行了。我们继续看看其他两个,进入invokeInitMethods方法中
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);
}
}
}
在这个方法里,一目了然就能看出来afterPropertiesSet先执行,最后执行了initMethod
结果
执行顺序为 constructor > postConstruct > afterPropertiesSet > initMethod