@PostConstruct、InitializingBean和initMethod执行顺序&源码分析

先看一个例子

public class TestBean implements InitializingBean {

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

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

    public void initMethod(){
        System.out.println("initMethod...");
    }
}
@Configuration(proxyBeanMethods = false)
public class TestConfig {

    @Bean(initMethod = "initMethod")
    public TestBean testBean() {
        return new TestBean();
    }

}

输出如下

postConstruct...
afterPropertiesSet...
initMethod...

所以顺序为@PostConstruct > InitializingBean > initMethod

创建Bean的过程中分为三步

  1. 实例化,:AbstractAutowireCapableBeanFactory#createBeanInstance
  2. 填充属性:AbstractAutowireCapableBeanFactory#populateBean
  3. 初始化:AbstractAutowireCapableBeanFactory#initializeBean

这里应该关注初始化阶段,也就是initializeBean方法
直接debug定位到对testBean的处理

在这里插入图片描述

注意BeanPostProcessor中有个CommonAnnotationBeanPostProcessor
@PostConstruct就是在这里面处理的
在这里插入图片描述

CommonAnnotationBeanPostProcessor的部分继承关系如下
顶层BeanPostProcessor中的两个方法(前置处理和后置处理),在InitDestroyAnnotationBeanPostProcessor中被重写
看名字就大概知道是和初始化销毁相关的处理器
在这里插入图片描述

前置处理如下

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
	try {
		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;
}

findLifecycleMetadata => buildLifecycleMetadata

这个方法意义很明确,就是看类中有没有initAnnotationType和destroyAnnotationType类型的注解,
有的话分别加入到initMethods和destroyMethods中,最后构造一个生命周期元数据(LifecycleMetadata)返回

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
	if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
		return this.emptyLifecycleMetadata;
	}

	List<LifecycleElement> initMethods = new ArrayList<>();
	List<LifecycleElement> destroyMethods = new ArrayList<>();
	Class<?> targetClass = clazz;

	do {
		final List<LifecycleElement> currInitMethods = new ArrayList<>();
		final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
				LifecycleElement element = new LifecycleElement(method);
				currInitMethods.add(element);
				if (logger.isTraceEnabled()) {
					logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
				}
			}
			if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
				currDestroyMethods.add(new LifecycleElement(method));
				if (logger.isTraceEnabled()) {
					logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
				}
			}
		});

		initMethods.addAll(0, currInitMethods);
		destroyMethods.addAll(currDestroyMethods);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);

	return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
			new LifecycleMetadata(clazz, initMethods, destroyMethods));
}

initAnnotationType和destroyAnnotationType是InitDestroyAnnotationBeanPostProcessor中的两个属性

@Nullable
private Class<? extends Annotation> initAnnotationType;

@Nullable
private Class<? extends Annotation> destroyAnnotationType;

在CommonAnnotationBeanPostProcessor的构造函数中分别设置为PostConstruct和PreDestory

public CommonAnnotationBeanPostProcessor() {
	setOrder(Ordered.LOWEST_PRECEDENCE - 3);
	setInitAnnotationType(PostConstruct.class);
	setDestroyAnnotationType(PreDestroy.class);
	ignoreResourceType("javax.xml.ws.WebServiceContext");

	// java.naming module present on JDK 9+?
	if (jndiPresent) {
		this.jndiFactory = new SimpleJndiBeanFactory();
	}
}

接着回到一开始的InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
然后执行invokeInitMethods
就是取出上一步所有的initMethods进行反射调用
也就是执行@PostConstruct标注的方法

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

	// 以上已分析过
	LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
	try {
		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;
}
public void invokeInitMethods(Object target, String beanName) throws Throwable {
	Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
	Collection<LifecycleElement> initMethodsToIterate =
			(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
	if (!initMethodsToIterate.isEmpty()) {
		for (LifecycleElement element : initMethodsToIterate) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
			}
			element.invoke(target);
		}
	}
}

到这里就可以知道,@PostConstruct是在CommonAnnotationBeanPostProcessor(InitDestroyAnnotationBeanPostProcessor)的postProcessBeforeInitialization(初始化前置)中处理的

回到AbstractAutowireCapableBeanFactory#initializeBean
以上是处理了applyBeanPostProcessorsBeforeInitialization
紧接着下面就是invokeInitMethods(初始化)和applyBeanPostProcessorsAfterInitialization(初始化后置)

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	// ...

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 初始化前置处理
		// 执行@PostConstruct
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		// 初始化
		// 执行InitializingBean#afterPropertiesSet,initMethod
		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;
}

invokeInitMethods方法中分成两部分

  1. 调用InitializingBean#afterPropertiesSet
  2. 调用自定义的initMethod
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
		throws Throwable {

	boolean isInitializingBean = (bean instanceof InitializingBean);
	if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("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.hasAnyExternallyManagedInitMethod(initMethodName)) {
			invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

在这里插入图片描述

参考
https://www.cnblogs.com/april-chen/p/8182631.html
https://developer.aliyun.com/article/766880

  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值