好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring Lifecycle的使用小结

前言

小杰在前面的文章讲过可以使用 @PostConstruct 、 InitializingBean 、 xml init 、 @PreDestroy 、 DisposableBean 、 xml destroy 来处理 Bean 的初始化和销毁,上述这些操作是属于 Bean 生命周期的。

那如果我想在容器本身的生命周期(比如容器启动、停止)上做一些工作怎么办呢?Spring 提供了以下接口。

Lifecycle

定义启动/停止生命周期方法的通用接口。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public interface Lifecycle {

     /**

      * 容器启动后调用

      */

     void start();

     /**

      * 容器停止时调用

      */

     void stop();

        

    /**

      * 检查此组件是否正在运行。

      * 1. 只有该方法返回false时,start方法才会被执行。

      * 2. 只有该方法返回true时,stop()方法才会被执行。

      */

     boolean isRunning();

}

自定义Lifecycle实现类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@Component

public class CustomizeLifecycle implements Lifecycle {

     private volatile boolean running = false ;

     @Override

     public void start() {

         running = true ;

         System.out.println( "start ==== " );

     }

     @Override

     public void stop() {

         running = false ;

         System.out.println( "stop ==== " );

     }

     @Override

     public boolean isRunning() {

         return running;

     }

}

测试

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@ComponentScan (basePackages = { "com.gongj.lifecycle" })

public class AppApplication {

     public static void main(String[] args) {

         AnnotationConfigApplicationContext context =

                 new AnnotationConfigApplicationContext(AppApplication. class );

         context.start();

         context.stop();

     }

}

结果:

isRunning ====> false

start ====>

isRunning ====> true

stop ====>

使用 Lifecycle 这种方式,需要显示的调用容器的 start 、 stop 方法。 显得笨重,所以我们使用另外一种方式 : SmartLifecycle 。

SmartLifecycle

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public interface SmartLifecycle extends Lifecycle, Phased {

     int DEFAULT_PHASE = Integer.MAX_VALUE;

     default boolean isAutoStartup() {

         return true ;

     }

     default void stop(Runnable callback) {

         stop();

         callback.run();

     }

     @Override

     default int getPhase() {

         return DEFAULT_PHASE;

     }

}

看到的源码定义, SmartLifecycle 除了继承 Lifecycle 之外,还继承了 Phased 。并且新增了几个方法:

isAutoStartup:是否自动启动。为 treu,则自动调用 start() ;为 false,则需要显示调用 start() 。 stop:当 isRunning 方法返回 true 时,该方法才会被调用。 getPhase:来自于 Phased 接口,当容器中有多个实现了 SmartLifecycle 的类,这个时候可以依据 getPhase 方法返回值来决定 start 方法、 stop 方法的执行顺序。 start 方法执行顺序按照 getPhase 方法返回值从小到大执行,而 stop 方法则相反。比如: 启动时:1 比 3 先执行,-1 比 1 先执行,退出时:3 比 1 先退出,1 比 -1 先退出。

自定义SmartLifecycle实现类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

@Component

public class CustomizeSmartLifecycle implements SmartLifecycle {

     private volatile boolean running = false ;

     @Override

     public void start() {

         running = true ;

         System.out.println( "CustomizeSmartLifecycle start()" );

     }

     @Override

     public void stop() {

         System.out.println( "CustomizeSmartLifecycle stop()" );

         running = false ;

     }

     @Override

     public boolean isRunning() {

         System.out.println( "CustomizeSmartLifecycle isRunning() ==== " + running);

         return running;

     }

     @Override

     public boolean isAutoStartup() {

         return true ;

     }

     @Override

     public void stop(Runnable callback) {

         System.out.println( "CustomizeSmartLifecycle stop(Runnable callback)" );

         callback.run();

     }

     @Override

     public int getPhase() {

         return 1 ;

     }

}

将代码进行启动,控制台打印如下内容:

?

1

2

3

4

5

6

7

8

9

public static void main(String[] args) {

     AnnotationConfigApplicationContext context =

         new AnnotationConfigApplicationContext(AppApplication. class );

     //context.start();

     //context.stop();

}

结果:

CustomizeSmartLifecycle isRunning() ==== false

CustomizeSmartLifecycle start()

发现并没有执行 stop 方法,这是因为容器问题。如果在 Spring Boot 项目会自动执行的,小伙伴可以试一试。

在本例中,还是需要显示调用 stop 方法。

?

1

2

3

4

5

6

7

8

9

10

11

public static void main(String[] args) {

     AnnotationConfigApplicationContext context =

         new AnnotationConfigApplicationContext(AppApplication. class );

     //context.start();

     context.stop();

}

结果:

CustomizeSmartLifecycle isRunning() ==== false

CustomizeSmartLifecycle start()

CustomizeSmartLifecycle isRunning() ==== true

CustomizeSmartLifecycle stop(Runnable callback)

发现执行了 stop(Runnable callback) ,并没有执行 stop 方法。这是因为当前类是 SmartLifecycle 的子类,如果要执行 stop 方法,需要在 stop(Runnable callback) 显示调用。

?

1

2

3

4

5

6

7

8

9

10

11

@Override

public void stop(Runnable callback) {

     System.out.println( "CustomizeSmartLifecycle stop(Runnable callback)" );

     stop();

     callback.run();

}

或者

@Override

public void stop(Runnable callback) {

     SmartLifecycle. super .stop(callback);

}

启动结果如下:

CustomizeSmartLifecycle isRunning() ==== false
CustomizeSmartLifecycle start()
CustomizeSmartLifecycle isRunning() ==== true
CustomizeSmartLifecycle stop(Runnable callback)
CustomizeSmartLifecycle stop()

注意:在 stop(Runnable callback) 方法中不要忘记调用 callback.run() 方法。否则 DefaultLifecycleProcessor 会认为这个 SmartLifecycle 没有 stop 完成,程序会等待一定时间,默认30秒后才会自动结束。

?

1

2

3

4

5

6

@Override

public void stop(Runnable callback) {

     System.out.println( "CustomizeSmartLifecycle stop(Runnable callback)" );

     //stop();

     //callback.run();

}

多个实现类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

@Component

public class CustomizeSmartLifecycle2 implements SmartLifecycle {

     private volatile boolean running = false ;

     @Override

     public void start() {

         running = true ;

         System.out.println( "CustomizeSmartLifecycle2 start() =====>" );

     }

     @Override

     public void stop() {

         System.out.println( "CustomizeSmartLifecycle1 stop() =====>" );

         running = false ;

     }

     @Override

     public boolean isRunning() {

         System.out.println( "CustomizeSmartLifecycle2 isRunning() =====> " + running);

         return running;

     }

     @Override

     public boolean isAutoStartup() {

         return true ;

     }

     @Override

     public void stop(Runnable callback) {

         System.out.println( "CustomizeSmartLifecycle2 stop(Runnable callback) =====>" );

         callback.run();

     }

     @Override

     public int getPhase() {

         return - 1 ;

     }

}

getPhase 方法返回 -1。按照前面所说的结论,那就是 CustomizeSmartLifecycle2 的 start 方法会先执行,然后 CustomizeSmartLifecycle2 的 stop 方法最后执行。我们一起来看看执行结果吧!

?

1

2

3

4

5

6

public static void main(String[] args) {

     AnnotationConfigApplicationContext context =

         new AnnotationConfigApplicationContext(AppApplication. class );

     //context.start();

     context.stop();

}

执行结果:

CustomizeSmartLifecycle2 isRunning() =====> false
CustomizeSmartLifecycle2 start() =====>
CustomizeSmartLifecycle isRunning() ==== false
CustomizeSmartLifecycle start()
CustomizeSmartLifecycle isRunning() ==== true
CustomizeSmartLifecycle stop(Runnable callback)
CustomizeSmartLifecycle2 isRunning() =====> true
CustomizeSmartLifecycle2 stop(Runnable callback) =====>

跟结论保持一致。

源码分析

基本的使用就到此结束啦!我们来结合源码分析分析吧!

我们来到 finishRefresh 方法的 getLifecycleProcessor().onRefresh(); 方法。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

protected void finishRefresh() {

     // Clear context-level resource caches (such as ASM metadata from scanning).

     clearResourceCaches();

     // Initialize lifecycle processor for this context.

     //为此上下文初始化生命周期处理器

     initLifecycleProcessor();

     // Propagate refresh to lifecycle processor first.

     // 默认调用 DefaultLifecycleProcessor 的 onRefresh 方法

     // 找出 Lifecycle Bean 执行 start 方法,默认情况下是没有Lifecycle Bean的,需要自己定义

     getLifecycleProcessor().onRefresh();

     // Publish the final event.

     // 发布事件  ContextRefreshedEvent 是一个事件

     publishEvent( new ContextRefreshedEvent( this ));

     // Participate in LiveBeansView MBean, if active.

     LiveBeansView.registerApplicationContext( this );

}

getLifecycleProcessor() 方法获得容器中的 LifecycleProcessor 对象,默认就是 DefaultLifecycleProcessor 。

LifecycleProcessor

?

1

2

3

4

5

6

7

8

9

10

11

12

public interface LifecycleProcessor extends Lifecycle {

     /**

      * Notification of context refresh, e.g. for auto-starting components.

      * 上下文刷新的通知,例如 用于自动启动组件

      */

     void onRefresh();

     /**

      * Notification of context close phase, e.g. for auto-stopping components.

      * 上下文关闭的通知,例如 用于自动停止组件。

      */

     void onClose();

}

接口中就定义的两个方法。 onRefresh 、 onClose 。

onRefresh

我们先来看一下 onRefresh 方法的内部逻辑,分析它是如何自动调用 start 方法的。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

@Override

public void onRefresh() {

     startBeans( true );

     this .running = true ;

}

private void startBeans( boolean autoStartupOnly) {

     // 获取所有的Lifecycle Bean

     Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();

     // 将Lifecycle Bean 按阶段分组,阶段通过实现 Phased 接口得到

     Map<Integer, LifecycleGroup> phases = new HashMap<>();

     // 遍历所有Lifecycle Bean 按阶段值进行分组

     lifecycleBeans.forEach((beanName, bean) -> {

         // 当autoStartupOnly=false,显示调用 start()方法进行启动,会触发全部的Lifecycle;

         // 当autoStartupOnly=true,调用容器的 refresh 方法启动,只会触发isAutoStartup方法返回true的SmartLifecycle

         if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {

             int phase = getPhase(bean);

             LifecycleGroup group = phases.get(phase);

             if (group == null ) {

                 group = new LifecycleGroup(phase, this .timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);

                 phases.put(phase, group);

             }

             group.add(beanName, bean);

         }

     });

     if (!phases.isEmpty()) {

         List<Integer> keys = new ArrayList<>(phases.keySet());

         Collections.sort(keys);

         for (Integer key : keys) {

             // 调用 Lifecycle 的 start 方法

             phases.get(key).start();

         }

     }

}

这里注意一下 autoStartupOnly 的值为 true 。

autoStartupOnly=true,调用容器的 refresh 方法,由容器调用 onRefresh 方法自动启动,只会触发 isAutoStartup 方法返回 true 的 SmartLifecycle 。而 isAutoStartup 属性,小杰在分析 SmartLifecycle 的时候已经讲过。 autoStartupOnly=false,显示调用 start() 方法进行启动,会触发全部的 Lifecycle

?

1

2

3

4

5

6

7

8

9

10

11

@Override

public void start() {

     getLifecycleProcessor().start();

     publishEvent( new ContextStartedEvent( this ));

}

//传入 false

@Override

public void start() {

     startBeans( false );

     this .running = true ;

}

onClose

onClose 在我没有找到调用点,但是 onClose 内部会调用 stopBeans() 方法。我们直接分析 stopBeans 方法。

stopBeans 方法跟 startBeans 的逻辑大体差不多,然后调用 stop 方法。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

@Override

public void onClose() {

     stopBeans();

     this .running = false ;

}

private void stopBeans() {

     // 获取所有的Lifecycle Bean

     Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();

     Map<Integer, LifecycleGroup> phases = new HashMap<>();

     lifecycleBeans.forEach((beanName, bean) -> {

         // 获得 phase 的值

         int shutdownPhase = getPhase(bean);

         LifecycleGroup group = phases.get(shutdownPhase);

         // 按阶段值进行分组

         if (group == null ) {

             // this.timeoutPerShutdownPhase 就是等待时间

             group = new LifecycleGroup(shutdownPhase, this .timeoutPerShutdownPhase, lifecycleBeans, false );

             phases.put(shutdownPhase, group);

         }

         group.add(beanName, bean);

     });

     if (!phases.isEmpty()) {

         List<Integer> keys = new ArrayList<>(phases.keySet());

         keys.sort(Collections.reverseOrder());

         for (Integer key : keys) {

             //调用 stop 方法

             phases.get(key).stop();

         }

     }

}

stop

创建一个 CountDownLatch 对象,如果 count 不为 0 ,则线程进行等待,默认等待 30 s。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

public void stop() {

   if ( this .members.isEmpty()) {

     return ;

   }

   if (logger.isDebugEnabled()) {

     logger.debug( "Stopping beans in phase " + this .phase);

   }

   this .members.sort(Collections.reverseOrder());

   // 创建 CountDownLatch 对象 ,count 为 smartMemberCount

   // smartMemberCount 为 SmartLifecycle Bean的个数

   CountDownLatch latch = new CountDownLatch( this .smartMemberCount);

   Set < String > countDownBeanNames = Collections.synchronizedSet( new LinkedHashSet < > ());

   Set < String > lifecycleBeanNames = new HashSet < > ( this .lifecycleBeans.keySet());

   for (LifecycleGroupMember member: this .members) {

     if (lifecycleBeanNames.contains(member.name)) {

       //调用 dostop 方法

       doStop( this .lifecycleBeans, member.name, latch, countDownBeanNames);

     } else if (member.bean instanceof SmartLifecycle) {

       // Already removed: must have been a dependent bean from another phase

       //将count值减1

       latch.countDown();

     }

   }

   try {

     //调用 await() 方法的线程会被挂起,等待一定的时间后,如果 count值还没有为 0 才继续执行

     latch.await( this .timeout, TimeUnit.MILLISECONDS);

     if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isInfoEnabled()) {

       logger.info( "Failed to shut down " + countDownBeanNames.size() + " bean" + (countDownBeanNames.size() > 1 ? "s" : "" ) + " with phase value " + this .phase + " within timeout of " + this .timeout + ": " + countDownBeanNames);

     }

   } catch (InterruptedException ex) {

     Thread.currentThread().interrupt();

   }

}

}

doStop

doStop 方法的逻辑很简单。区分是否是 SmartLifecycle 类型,如果是执行 stop(Runnable callback) 方法,反之执行 stop() 方法。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName,

                     final CountDownLatch latch, final Set<String> countDownBeanNames) {

     Lifecycle bean = lifecycleBeans.remove(beanName);

     if (bean != null ) {

         String[] dependentBeans = getBeanFactory().getDependentBeans(beanName);

         for (String dependentBean : dependentBeans) {

             doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames);

         }

         try {

             // 判断 isRunning 的值

             if (bean.isRunning()) {

                 // 如果是 SmartLifecycle 类型,则执行 stop(Runnable callback) 方法

                 if (bean instanceof SmartLifecycle) {

                     if (logger.isTraceEnabled()) {

                         logger.trace( "Asking bean '" + beanName + "' of type [" +

                                      bean.getClass().getName() + "] to stop" );

                     }

                     countDownBeanNames.add(beanName);

                     // 这里就是为什么要调用 callback.run() 的原因

                     // 传入的是一个 lambad 表达式,所以需要调用callback.run(),才会执行 lambad 体

                     // 在lambad 体才会执行 latch.countDown()

                     ((SmartLifecycle) bean).stop(() -> {

                         //将count值减1

                         latch.countDown();

                         countDownBeanNames.remove(beanName);

                         if (logger.isDebugEnabled()) {

                             logger.debug( "Bean '" + beanName + "' completed its stop procedure" );

                         }

                     });

                 }

                 else {

                     if (logger.isTraceEnabled()) {

                         logger.trace( "Stopping bean '" + beanName + "' of type [" +

                                      bean.getClass().getName() + "]" );

                     }

                     // 否则执行 stop() 方法

                     bean.stop();

                     if (logger.isDebugEnabled()) {

                         logger.debug( "Successfully stopped bean '" + beanName + "'" );

                     }

                 }

             }

             else if (bean instanceof SmartLifecycle) {

                 // Don't wait for beans that aren't running...

                 latch.countDown();

             }

         }

         catch (Throwable ex) {

             if (logger.isWarnEnabled()) {

                 logger.warn( "Failed to stop bean '" + beanName + "'" , ex);

             }

         }

     }

}

关于 Lifecycle 的使用与源码分析就到这啦!

到此这篇关于Spring Lifecycle的使用的文章就介绍到这了,更多相关Spring Lifecycle使用内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://juejin.cn/post/7086353052222881829

查看更多关于Spring Lifecycle的使用小结的详细内容...

  阅读:12次