spring提供了三种初始化方法:
1、@PostConstruct、@PreDestory
2、实现 InitializingBean DisposableBean 接口,并实现对应的afterPropertiesSet()和destroy()方法
3、设置init-method和destory-method
本文主要解析三个初始化和销毁方法的源码
1、三种初始化方法的优先级从高到低;在spring官方文档也有明确指出
Multiple lifecycle mechanisms configured for the same bean, with
different initialization methods, are called as follows:
Methods annotated with @PostConstruct
afterPropertiesSet() as defined by the InitializingBean callback interface
A custom configured init() method
Destroy methods are called in the same order:
Methods annotated with @PreDestroy
destroy() as defined by the DisposableBean callback interface
A custom configured destroy() method
优先级之所以是这样,和源码中对三种配置方式处理的优先级有关系
测试代码
public class UserService04 implements InitializingBean,DisposableBean {
public UserService04() {
}
@Override
public void destroy() throws Exception {
System.out.println("实现接口DisposableBean销毁");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("实现接口InitializingBean初始化");
}
public void init(){
System.out.println("initMethod");
}
public void destroyConfig(){
System.out.println("destroyMethod");
}
@PostConstruct
public void testPost(){
System.out.println("注解PostConstruct init");
}
@PreDestroy
public void testDestroy(){
System.out.println("注解PreDestroy 销毁");
}
}
@Configuration
@ComponentScan("com.springsource.initmethod")
public class InitMethodConfig {
@Bean(initMethod = "init",destroyMethod = "destroyConfig")
public UserService04 testUserService04(){
return new UserService04();
}
}
2、初始化方法
初始化方法的代码位置是在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
在该方法中,完成了bean的初始化方法回调和bean的动态代理对象生成,主要来看初始化回调方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
对于@PostConstruct和@PreDestroy这两个注解,是在applyBeanPostProcessorsBeforeInitialization()中完成处理的,而剩下两种初始化方法,是在invokeInitMethods()中完成的,所以,对于注解的方式,优先级最高
我们先来说invokeInitMethods()方法,也就是后两种初始化方法:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//这里是处理实现了InitializingBean接口的初始化方法
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();
}
}
//这里是来处理init-method方法
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);
}
}
}
可以看到,代码中是先判断当前bean是否是InitializingBean的实现类,然后优先调用了afterProperties();
然后再调用beanDefinition中对应的initMethod;需要说明的是:initMethod这种方式,对应的初始化方法和销毁方法,是在将bean添加到beanDefinitionMap中的时候,对bean进行了解析,获取到对应的initMethod和destroyMethod,然后放到了beanDefinition中
我们接着来说@PostConstruct和@PreDestroy注解的处理
该注解是由CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization和postProcessBeforeDestruction来处理的
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
/**
* 在初始化bean的时候,会在这里处理注解的初始化方法 @PostConstruct
* 从cache中获取到当前bean的元对象
* 在invokeInitMethods方法中,就是
*/
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;
}
这是初始化方法对应的处理类,在此之前,在第三个后置处理器调用的时候,会调用到org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition;在该方法中,会找出当前bean中对应的@PostConstruct和@PreDestroy注解对应的方法,存入到lifecycleMetadataCache这个map中
然后在调用postProcessBeforeInitialization()方法的时候,注解从map中遍历所有的初始化方法,然后依次调用
3、销毁方法
三个销毁方法是在调用
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
//这里是处理@PreDestroy注解对应的方法
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
// 处理实现了DisposableBean接口的类
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
//处理destroyMethod方法
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
调用链是这样的,可以看到,在销毁bean的时候,也是按照文章开头的顺序来进行销毁的;而对应的原理和初始化方法调用的原理是一样的