• spring扩展接口解析2--生命周期LifeCycle接口


    前言

    Spring容器本身是有生命周期的,比如容器启动则开始生命和容器关闭则结束生命,如果想让Spring容器管理的bean也同样有生命周期的话,比如数据库连接对象,当容器启动时,连接bean生命周期开启,当容器关闭时,连接bean生命周期结束。

    此时就可以用到Spring提供的一个扩展接口--Lifecycle接口

    一、Lifecycle接口定义

    Lifecycle接口一共定义了三个方法,分别如下:

     1 public interface Lifecycle {
     2 
     3         /**
     4          * 生命周期开始
     5          */
     6         void start();
     7 
     8         /**
     9          * 生命周期结束
    10          */
    11         void stop();
    12 
    13         /**
    14          * 判断当前bean是否是开始状态
    15          */
    16         boolean isRunning();
    17 
    18     }

    start():表示开启该对象的生命周期

    stop():表示结束该对象的生命周期

    isRunning():判断当前对象的生命周期是否时开始状态

    从接口的方法上很好理解,主要是开始和结束当前对象的生命周期,以及判断当前对象生命周期的状态。

    二、Lifecycle接口的扩展LifecycleProcessor接口

    Spring中提供了Lifecycle接口的子接口 LifecycleProcessor,从字面意思上看是Lifecycle接口的处理器,LifecycleProcessor接口定义如下:

     1 public interface LifecycleProcessor extends Lifecycle {
     2 
     3     /**
     4      * 刷新容器,自动开始生命周期
     5      */
     6     void onRefresh();
     7 
     8     /**
     9      * 关闭容器,自动结束生命周期
    10      */
    11     void onClose();
    12 
    13 }

    三、Spring容器的生命周期

    Spring容器是有生命周期的,因为Spring容器抽象类AbstractApplicationContext实现了Lifecycle接口,实现代码如下:

    1 LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
    2         if (this.lifecycleProcessor == null) {
    3             throw new IllegalStateException("LifecycleProcessor not initialized - " +
    4                     "call 'refresh' before invoking lifecycle methods via the context: " + this);
    5         }
    6         return this.lifecycleProcessor;
    7     }
     1 @Override
     2     public void start() {
     3         getLifecycleProcessor().start();
     4         publishEvent(new ContextStartedEvent(this));
     5     }
     6 
     7     @Override
     8     public void stop() {
     9         getLifecycleProcessor().stop();
    10         publishEvent(new ContextStoppedEvent(this));
    11     }
    12 
    13     @Override
    14     public boolean isRunning() {
    15         return (this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning());
    16     }

    从源码看出,AbstractApplicationContext的start和stop方法完全委托给了内部的LifecycleProcessor来执行的。而LifecycleProcessor的初始化是在AbstractactApplicationContext初始化时进行的

    AbstractApplicationContext初始化时,当容器全部初始化完毕之后会执行finishRefresh方法表示整个容器刷新完成了,执行逻辑如下:

     1 protected void finishRefresh() {
     2         // Clear context-level resource caches (such as ASM metadata from scanning).
     3         clearResourceCaches();
     4 
     5         //初始化LifecycleProcessor对象
     6         initLifecycleProcessor();
     7 
     8         //调用LifecycleProcessor对象的onRefresh()方法
     9         getLifecycleProcessor().onRefresh();
    10 
    11         // Publish the final event.
    12         publishEvent(new ContextRefreshedEvent(this));
    13 
    14         // Participate in LiveBeansView MBean, if active.
    15         LiveBeansView.registerApplicationContext(this);
    16     }

    在finishRefresh方法中首先是初始化了内部的LifecycleProcessor对象,然后调用了该对象的onRefresh()方法,而初始化LifecycleProcessor方法的逻辑也不复杂,首先是从BeanFactory中找到自定义的LifecycleProcessor,如果没有用户自定义的,则创建一个默认的LifecycleProcessor实现类DefaultLifecycleProcessor对象,源码如下:

     1 protected void initLifecycleProcessor() {
     2         ConfigurableListableBeanFactory beanFactory = getBeanFactory();
     3 /** 如果BeanFactory中有自定义的LifecycleProcessor的bean,则直接用自定义的*/
     4         if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
     5             this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
     7             if (logger.isTraceEnabled()) {
     8                 logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
     9             }
    10         }
    11         else {
    12 /** 如果没有自定义,则创建默认的实现类DefaultLifecycleProcesor*/
    13             DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
    14             defaultProcessor.setBeanFactory(beanFactory);
    15             this.lifecycleProcessor = defaultProcessor;
    16             beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
    17             if (logger.isTraceEnabled()) {
    18                 logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
    19                         "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
    20             }
    21         }
    22     }

    接下来在分析下默认的LifecycleProcessor的处理逻辑,实现了LifecycleProcessor接口的实现源码如下:

     1        /**
     2     * 执行startBeans(false)方法开启所有实现了Lifecycle接口的bean的生命周期
     3      */
     4     @Override
     5     public void start() {
     6         startBeans(false);
     7         this.running = true;
     8     }
     9 
    10     /**
    11      * 执行stopBeans()方法关闭所有实现了Lifecycle接口的bean的生命周期
    12      */
    13     @Override
    14     public void stop() {
    15         stopBeans();
    16         this.running = false;
    17     }
    18 
    19     @Override
    20     public void onRefresh() {
    21         startBeans(true);
    22         this.running = true;
    23     }
    24 
    25     @Override
    26     public void onClose() {
    27         stopBeans();
    28         this.running = false;
    29     }
    30 
    31     @Override
    32     public boolean isRunning() {
    33         return this.running;
    34     }

    可以看出实现逻辑也不复杂,start()方法和onRefresh()方法分别都是执行了startBeans方法;stop方法和onClose方法都是执行了stopBeans方法,并且内部有一个running属性用于表示当前的生命周期状态。

    所以核心逻辑都是在startBeans和stopBeans两个方法中。

    startBeans源码解析:

     1 /** 开始bean的生命周期
     2      * @param autoStartupOnly:自动开启还是手动开启
     3      * */
     4     private void startBeans(boolean autoStartupOnly) {
     5         /**
     6          * 1.调用getLifecycleBeans方法获取所有实现了Lifecycle接口的bean
     7          *  实现逻辑就是调用BeanFactory的getBeanNamesForType(LifeCycle.class)方法来获取所有bean
     8          * */
     9         Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    10         Map<Integer, LifecycleGroup> phases = new HashMap<>();
    11         /**
    12          * 2.遍历所有Lifecycle的bean,按不同阶段进行分组,同组的封装为LifecycleGroup对象
    13          * */
    14         lifecycleBeans.forEach((beanName, bean) -> {
    15             if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
    16                 int phase = getPhase(bean);
    17                 LifecycleGroup group = phases.get(phase);
    18                 if (group == null) {
    19                     group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
    20                     phases.put(phase, group);
    21                 }
    22                 group.add(beanName, bean);
    23             }
    24         });
    25         /**
    26          * 3.遍历所有LifecycleGroup,调用LifecycleGroup的start方法
    27          * */
    28         if (!phases.isEmpty()) {
    29             List<Integer> keys = new ArrayList<>(phases.keySet());
    30             Collections.sort(keys);
    31             for (Integer key : keys) {
    32                 phases.get(key).start();
    33             }
    34         }
    35     }

    主要分成以下三步:

    第一步:从BeanFactory中获取所有实现了Lifecycle接口的bean

    第二步:遍历所有实现了Lifecycle接口的bean,按不同阶段进行分组,同一组的bean封装成LifecycleGroup对象

    第三步:遍历所有组,调用LifecycleGroup对象的start方法

    LifecycleGroup对象的start方法源码如下:

     1 public void start() {
     2             if (this.members.isEmpty()) {
     3                 return;
     4             }
     5             if (logger.isDebugEnabled()) {
     6                 logger.debug("Starting beans in phase " + this.phase);
     7             }
     8 /** 将Lifecycle对象进行排序*/
     9             Collections.sort(this.members);
    10 /** 遍历调用doStart方法开启Lifecycle对象的生命周期*/
    11             for (LifecycleGroupMember member : this.members) {
    12                 doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
    13             }
    14         }
     1 private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
     2         /**
     3          * 1.根据beanName从集合中获取Lifecycle对象并移除
     4          * */
     5         Lifecycle bean = lifecycleBeans.remove(beanName);
     6         if (bean != null && bean != this) {
     7             /**
     8              * 2.如果有依赖,则先开启依赖bean的生命周期
     9              * */
    10             String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
    11             for (String dependency : dependenciesForBean) {
    12                 doStart(lifecycleBeans, dependency, autoStartupOnly);
    13             }
    14             if (!bean.isRunning() &&
    15                     (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
    16                 try {
    17                     /**
    18                      * 3.调用Lifecycle对象的start方法开启生命周期
    19                      * */
    20                     bean.start();
    21                 }
    22                 catch (Throwable ex) {
    23                     throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
    24                 }
    25             }
    26         }
    27     }

    总结:

    startBeans整体逻辑如下:

    1、从BeanFactory中获取所有实现了Lifecycle接口的bean

    2、将所有Lifecycle按阶段进行分组

    3、遍历所有阶段的组,遍历每个组内的所有Lifecycle对象,如果Lifecycle对象有依赖bean就先开启依赖bean的生命周期,然后直接执行Lifecycle对象的start方法

    同理,stopBeans的整体逻辑和startBeans完全一样,只不过一个是执行LifeCycle的start方法一个是执行LifeCycle的stop方法。

    四、Lifecycle接口的扩展SmartLifecycle接口

    SmartLifecycle接口继承之Lifecycle接口和Phased接口,源码如下:

     1 public interface SmartLifecycle extends Lifecycle, Phased {
     2 
     3     /**
     4      * 默认优先级,Integer的最大值
     5      */
     6     int DEFAULT_PHASE = Integer.MAX_VALUE;
     7 
     8 
     9     /**
    10      * 是否自动启动,默认为true
    11      */
    12     default boolean isAutoStartup() {
    13         return true;
    14     }
    15 
    16     /**
    17      * 默认直接执行stop方法,并执行回调方法
    18      */
    19     default void stop(Runnable callback) {
    20         stop();
    21         callback.run();
    22     }
    23 
    24     /**
    25      * 获取优先级,启动时值越小越先启动;停止时值越小越后停止
    26      */
    27     @Override
    28     default int getPhase() {
    29         return DEFAULT_PHASE;
    30     }
    31 
    32 }

    SmartLifecycle接口有一个优先级,如果没有实现SmartLifecycle接口的其他的Lifecycle的优先级为0,启动的时候按phase的值从小到大执行;关闭的时候按phase的值从大到小执行。

    isAutoStartup()方法表示Spring容器刷新的时候自动执行start()方法,返回true表示会;返回false则不会,那么就需要手动调用start方法才可以执行。

    Spring容器初始化完成之后,会调用LifecycleProcessor的onRefresh方法刷新整个上下文,但是此时的AbstractApplicationContext实际上还并没有执行start方法,但是如果有bean需要在Spring容器刷新的时候就调用start方法,那么就可以使用SmartLifecycle,

    当SmartLifecycle接口的isAutoStartup方法返回true时表示只要Spring容器刷新了就会调用该bean的start方法,否则必须要等到Spring容器执行了start方法之后才会执行SmartLifecycle对象的start方法。

    测试案例如下:

    定义两个bean,一个设置isAutoStartup为true,一个为false

     1 public class AutoBean implements SmartLifecycle {
     2 
     3     boolean running;
     4 
     5     public boolean isAutoStartup() {
     6         return true;
     7     }
     8 
     9     @Override
    10     public void start() {
    11         System.out.println("AutoBean 执行start方法");
    12         running = true;
    13     }
    14 
    15     @Override
    16     public void stop() {
    17         System.out.println("AutoBean 执行stop方法");
    18         running = false;
    19     }
    20 
    21     @Override
    22     public boolean isRunning() {
    23         return running;
    24     }
    25 }
     1 public class NoAutoBean implements SmartLifecycle {
     2 
     3     boolean running;
     4 
     5     public boolean isAutoStartup() {
     6         return false;
     7     }
     8 
     9     @Override
    10     public void start() {
    11         System.out.println("NoAutoBean 执行start方法");
    12         running = true;
    13     }
    14 
    15     @Override
    16     public void stop() {
    17         System.out.println("NoAutoBean 执行stop方法");
    18         running = false;
    19     }
    20 
    21     @Override
    22     public boolean isRunning() {
    23         return running;
    24     }
    25 }

    测试代码如下:

    1  public static void main(String[] args) throws Exception {
    2         System.out.println("---->初始化Spring容器");
    3         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
    4         System.out.println("---->启动Spring容器");
    5         context.start();
    6         System.out.println("---->关闭Spring容器");
    7         context.stop();
    8     }

    测试代码中,先初始化Spring容器,然后启动Spring容器,最后在关闭Spring容器,测试结果如下:

    ---->初始化Spring容器
    AutoBean 执行start方法
    ---->启动Spring容器
    NoAutoBean 执行start方法
    ---->关闭Spring容器
    AutoBean 执行stop方法
    NoAutoBean 执行stop方法

     从结果可以看出,当SmartLifecycle的isAutoStartup为true时,只要Spring容器刷新了就会自动执行start方法,而isAutoStartup为false时,只有当容器执行了start方法之后才会执行start方法

    所以如果想要Lifecycle对象随着Spring容器初始化之后就开启,就可以采用实现SmartLifecycle接口的方式。

    五、总结

    1、Lifecycle接口用于实现bean的生命周期,执行start方法开启生命周期;执行stop方法结束生命周期

    2、ApplicationContext通过LifecycleProcessor来管理所有bean的生命周期,当Spring容器启动或者刷新时,都会调用容器中所有实现了Lifecycle接口的bean的start方法,关闭时调用所有实现了Lifecycle接口的bean的stop方法

    3、SmartLifecycle可以实现异步回调执行stop方法,用于结束生命周期之前的收尾业务逻辑处理;并且可以设置是否在容器刷新时自动开启生命周期

  • 相关阅读:
    kubectl exec 执行 容器命令
    centos下通过yum安装redis-cli
    windows下 使用ip地址反查主机名的命令
    O365(世纪互联)SharePoint 之文档库使用小记
    SharePoint 2016 图文安装教程
    SharePoint 2013 激活标题字段外的Menu菜单
    SharePoint 2013 定制搜索显示模板(二)
    SharePoint 2013 定制搜索显示模板
    SharePoint 2013 网站搜索规则的使用示例
    SharePoint 2013 搜索功能,列表项目不能完全被索引
  • 原文地址:https://www.cnblogs.com/jackion5/p/13276181.html
Copyright © 2020-2023  润新知