init-method,@postcontruct,afterPropertiesSet的先后顺序
Posted 镇屌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了init-method,@postcontruct,afterPropertiesSet的先后顺序相关的知识,希望对你有一定的参考价值。
在牛客面经上遇到的一个面试题。突然想尝试下
然后就开始做了
测试
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
TestDao testDao = applicationContext.getBean(TestDao.class);
((ClassPathXmlApplicationContext) applicationContext).close();
测试的bean
@Component
public class TestDao implements InitializingBean, DisposableBean {
public TestDao() {
System.out.println("constructor");
}
@Async
public void query(){
System.out.println("Hello Spring!");
}
@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");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@PreDestroy
public void PreDestroy(){
System.out.println("PreDestroy");
}
public void destroyMethod(){
System.out.println("destroyMethod");
}
}
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="testDao" class="com.test.dao.TestDao" init-method="InitMethod" destroy-method="destroyMethod"></bean>
</beans>
执行之后打印的结果
总的来说就是打印的结果是构造方法->注解@PostConstruct方法->InitializingBean接口的afterPropertiesSet方法->xml中配置的init-method方法
同理销毁也是一样注解@PreDestroy方法->DisposableBean接口的destroy方法->xml中配置的destroy-method方法
源码
通过断点调试发现几个初始化方法都定位到了AbstractAutowireCapableBeanFactory的initializeBean方法中
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()) {
//此处执行的是@PostConstruct注解的方法 InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//执行的是afterPropertiesSet和init-method方法
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;
}
后面执行的两个方法
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 {
//执行afterPropertiesSet方法
((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)) {
//执行的是xml中自定义的init-method方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
以上是关于init-method,@postcontruct,afterPropertiesSet的先后顺序的主要内容,如果未能解决你的问题,请参考以下文章
spring 之 init-method & InitializingBean
如何控制 Spring 中 bean init-method 调用的顺序?
Spring Bean init-method 和 destroy-method实例
?spring中afterPropertiesSet方法与init-method配置描述