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方法,用于结束生命周期之前的收尾业务逻辑处理;并且可以设置是否在容器刷新时自动开启生命周期

原文地址:https://www.cnblogs.com/jackion5/p/13276181.html