先看两个注解:
@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())))); }