spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

先看两个注解:

@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销毁之前执行。

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 

容器关闭:

手动关闭,手动关闭容器,容器中的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(); 后面还可以有其它的逻辑。

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 在 DefaultSingletonBeanRegistry类中有一个属性 disposableBeans 记录所有实现了DisposableBean 接口的,在destroyBeans()方法中会遍历这个集合,找到对应的bean,然后调用里面的destroy方法。

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 


 

但是这里的disposableBeans 这个map中不止只有实现了DisposableBean 这个接口的bean,还有其它的一些bean,这个map的赋值是在创建bean的时候进行的,在doCreateBean中。 

 AbstractAutowireCapableBeanFactory#doCreateBean中,在创建完bean之后,最后一步就是注入disposable相关的bean到disposableBeans这个map中,

 spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 

 

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;
}           

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 

 


 

注意点:

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析这个map的value是Object的,调用的时候把它强转成DisposableBean,然后调用destroy方法,但是我们上面看它注入时候是注入的DisposableBeanAdapter 类。

这里用到了适配器模式。我们看DisposableBeanAdapter 这个类实现了DisposableBeanAdapter 接口。

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 

 所以调用的时候,执行的是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));
            }
        }
    }

 

构造函数中:

 

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 

 

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);
    }

 

 

总结: 

 

spring源码分析(六) 销毁方法,初始化之前的方法加载和执行过程分析

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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()))));
}
上一篇:docker(3)安装ui、安装efk


下一篇:使用Java8提供的Duration类制作字幕时间轴调整工具