先看两个注解:
@Component
public class People {
// bean销毁之前执行,容器关闭的时候执行
@PreDestroy
public void predesory(){
System.out.println("predesory 执行了");
}
// bean创建之前执行
@PostConstruct
public void init(){
System.out.println("PostConstruct 执行了");
}
}
bean销毁之前执行的方法还有一种定义的方式,就是实现 DisposableBean 接口,里面有一个destory方法,这个方法在容器关闭之前,bean销毁之前执行。
容器关闭:
手动关闭,手动关闭容器,容器中的bean会被正常销毁。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
applicationContext.close();
注册一个钩子函数。
// 注入一个关闭的钩子,引用是jvm的一个关闭钩子(线程),也就是当前jvm关闭的时候,spring容器也会关闭,bean会销毁。
applicationContext.registerShutdownHook();
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
上面两个注解能够正常执行,和上篇分析的 CommonAnnotationBeanPostProcessor 有关系,它不止处理@Resource注解,也有其它作用。
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
上面继承了一个 InitDestroyAnnotationBeanPostProcessor ,这个类有个方法:postProcessMergedBeanDefinition,在CommonAnnotationBeanPostProcessor 子类中中这个方法还有一个功能:@Resource ,@Autowire都经过这个方法找到注入点的
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//调用父类的方法找到
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// 找到注入点
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
父类:postProcessMergedBeanDefinition 方法
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 生命周期有关的注解方法封装成 LifecycleMetadata
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
// 如果这个bean不是候选者bean,直接返回空的
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
// 存放初始化方法的element集合
List<LifecycleElement> initMethods = new ArrayList<>();
// 存放销毁方法的element集合
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
// 和前面找@Autowire的注解很像
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 初始化注解方法查找
//this.initAnnotationType 通过 setInitAnnotationType 设置的,这个方法可以自己调用设置自定义的注解
// 默认在子类 CommonAnnotationBeanPostProcessor 构造函数中调用注入 setInitAnnotationType(PostConstruct.class)
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
// 方法封装成 LifecycleElement
LifecycleElement element = new LifecycleElement(method);
// 放入 currInitMethods中
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
// 销毁方法查找
// this.destroyAnnotationType 是通过 setDestroyAnnotationType方法设置的,
// 默认也是在子类的构造函数中注入默认的 setDestroyAnnotationType(PreDestroy.class)
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));
}
在InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization 方法中调用initMethods 集合中存放的初始化之前的方法。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 会从缓存中获取了
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//调用 postProcessMergedBeanDefinition方法中找到的注解标注的初始化方法
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;
}
就是调用反射调用那些加了PostConstruct 注解的方法。
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);
}
}
}
销毁方法执行:
主要看applicationContext.close(); 这个方法,里面调用了doClose方法,通过发布关闭事件关闭容器。注意:spring容器关闭,并不是JVM关闭,比如applicationContext.close(); 后面还可以有其它的逻辑。
在 DefaultSingletonBeanRegistry类中有一个属性 disposableBeans 记录所有实现了DisposableBean 接口的,在destroyBeans()方法中会遍历这个集合,找到对应的bean,然后调用里面的destroy方法。
但是这里的disposableBeans 这个map中不止只有实现了DisposableBean 这个接口的bean,还有其它的一些bean,这个map的赋值是在创建bean的时候进行的,在doCreateBean中。
AbstractAutowireCapableBeanFactory#doCreateBean中,在创建完bean之后,最后一步就是注入disposable相关的bean到disposableBeans这个map中,
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
//只有非原型bean才会去执行它们的构造和销毁的前置方法
// 并且还要是 requiresDestruction中指定的几种方式
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
//如果上面判断有销毁方法,就封装成DisposableBeanAdapter 类
// put进 disposableBeans 这个map中,放进去的只是个适配器
// 从disposableBeans.get出来的对象要强转成DisposableBean调用close方法
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
requiresDestruction(bean, mbd) 中判断bean中是否销毁的方法,有写重要的逻辑判断。
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
// 判断某个bean是否有销毁的方法
// 1: 实现了Disposable 或者AutoCloseable接口
// 2: BeanDefinition中定义了destroyMethodName方法
// 类中是否存在@PreDestroy注解的方法
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
第一个判断非空判断不用多说。
第二个判断:DisposableBeanAdapter.hasDestroyMethod(bean, mbd)
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
// 首先判断 bean是否实现了 DisposableBean,AutoCloseable接口
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
// beanDefinition 中定义了 destroyMethodName,如果xml定义的bean 可以通过destroy-method属性指定这个name
String destroyMethodName = beanDefinition.getDestroyMethodName();
// 如果从 beanDefinition.getDestroyMethodName() 得到的destroyName是 INFER_METHOD,那么bean中定义的 close方法或者shutdown 方法都可以作为销毁的方法
// 但是要注意,这个close,shutdown方法的bean要以@Bean的方式注入到容器中才会生效。因为@Bean中的有默认的 AbstractBeanDefinition.INFER_METHOD destroyName
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName)) {
return (ClassUtils.hasMethod(bean.getClass(), CLOSE_METHOD_NAME) ||
ClassUtils.hasMethod(bean.getClass(), SHUTDOWN_METHOD_NAME));
}
return StringUtils.hasLength(destroyMethodName);
}
(hasDestructionAwareBeanPostProcessors() &&DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))
hasDestructionAwareBeanPostProcessors(): 判断容器中是否有实现DestructionAwareBeanPostProcessor 接口的bean,之前提到的CommonAnnotationBeanPostProcessor继承的InitDestroyAnnotationBeanPostProcessor 便实现了这个接口,
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()) 则判断bean中是否有@PreDestroy注解标注的方法。
public static boolean hasApplicableProcessors(Object bean, List<BeanPostProcessor> postProcessors) {
if (!CollectionUtils.isEmpty(postProcessors)) {
for (BeanPostProcessor processor : postProcessors) {
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
// 这里会走到 之前提到的CommonAnnotationBeanPostProcessor继承的InitDestroyAnnotationBeanPostProcessor 便实现了DestructionAwareBeanPostProcessor这个接口
// InitDestroyAnnotationBeanPostProcessor#requiresDestruction
if (dabpp.requiresDestruction(bean)) {
return true;
}
}
}
}
return false;
}
注意点:
这个map的value是Object的,调用的时候把它强转成DisposableBean,然后调用destroy方法,但是我们上面看它注入时候是注入的DisposableBeanAdapter 类。
这里用到了适配器模式。我们看DisposableBeanAdapter 这个类实现了DisposableBeanAdapter 接口。
DisposableBeanAdapter#destroy, 这个方法会根据不同情况的调用不同的销毁方法。
@Override
public void destroy() {
// 执行@PreDestroy方法
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
// bean实现了 DisposableBean 接口而且前面通过后置处理器找到的destroyName不是 "destroy"
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("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) 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);
}
}
}
// 在构造函数中 得到的 destroyName
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
构造函数中:
private String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
// 只返回一个值 指定的destroy方法名 close方法 shutdown方法
// 如果 beanDefinition 中指定了destroy方法,判断是否为默认值 INFER_METHOD
// 是默认值或者实现了 AutoCloseable接口 走下面的逻辑
String destroyMethodName = beanDefinition.getDestroyMethodName();
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
(destroyMethodName == null && bean instanceof AutoCloseable)) {
// Only perform destroy method inference or Closeable detection
// in case of the bean not explicitly implementing DisposableBean
if (!(bean instanceof DisposableBean)) {
try {
return bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex) {
try {
return bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex2) {
// no candidate destroy method found
}
}
}
return null;
}
return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
}
总结:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 生命周期有关的注解方法封装成 LifecycleMetadata
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
// 判断某个bean是否有销毁的方法
// 1: 实现了Disposable 或者AutoCloseable接口
// 2: BeanDefinition中定义了destroyMethodName方法
// 类中是否存在@PreDestroy注解的方法
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}