Spring-Lifecycle分析

Spring-Lifecycle分析

简介

Lifecycle接口在项目中看到过一眼,之前都不知道这个。这篇文章就来介绍介绍他。

在这里插入图片描述

从类图看出,主要有三个接口,最主要的有Lifecycle和SmartLifecycle接口。

首先要知道,Lifecycle接口的语义就是启动停止。所以,实现他的类,都是需要启动和停止的类,并且SmartLifecycle在他的语义上面,增加了Pahsed(我觉得分组更适合),和自动启动的功能。

功能

  1. Lifecycle

    它是一个通用的接口,主要用于生命周期的控制操作。定义了start/stop的方法。可以被bean和容器实现,如果是容器实现的话,容器会传播一个信号,应用给容器中所有的实现了这个接口的bean。

    需要注意,这个接口里面的start方法是需要手动调用的。没有自动启动的含义(自动启动就是在容器启动了之后,容器会自动调用)。

  2. SmartLifecycle

    扩展了Lifecycle。主要是用于需要在 ApplicationContext 启动自动启动语义的bean。

  3. Phased

    阶段对象,提供了一个int getPhase();,接口是用来表示功能的,那么这个接口就用来表示阶段(我觉得分组更加的适合把)。

区别

Lifecycle接口

用来表示生命周期,提供了两个方法(start/stop),用来启动和停止。isRunning方法表示当前是否已经启动。(这个接口没有自动启动的意思,如果要启动,就需要手动启动,停止是在ApplicationContext关闭的时候会调用)。

如果已经启动,再次调用的话,不应该就要抛出异常了。

如果是容器实现了这个接口(比如ConfigurableApplicationContext),容器会唤醒所有的实现了这个接口的组件。

如果已经停止,再次调用,也不应该抛出异常。

isRuning方法返回是否运行,对于容器来说,当他里面所有的component都停止了,才会返回ture。

public interface Lifecycle {

	void start();

	void stop();

	boolean isRunning();
}

SmartLifecycle接口

拓展了Lifecycle接口,增加了自动启动的功能,这个功能主要是在ApplicationContext refresh的时候会自动启动。

此外还增了对异步停止的支持,自动了了一个stop(Runnable calllback)方法,主要是给DefaultLifecycleProcessor来做调用的。

public interface SmartLifecycle extends Lifecycle, Phased {

	// 默认的阶段
	int DEFAULT_PHASE = Integer.MAX_VALUE;

  // 是否要自动启动,注意,这个default关键词。
	default boolean isAutoStartup() {
		return true;
	}
  /**
  停止在运行的Lifecycle component。要注意,他提供了一个回调方法用于,支持顺序和并发,给LifecycleProcessor使用。回调方法必须是在内部的stop方法调用完了之后,才调用这个
  */
	default void stop(Runnable callback) {
		stop();
		callback.run();
	}

	// 返回所处的阶段。有默认值。
	@Override
	default int getPhase() {
		return DEFAULT_PHASE;
	}
}

上面分析了两个接口的主要功能,下面分析这些接口是在哪里调用的。

解析

在LifeCycle中,还有一个需要关注的实现类。

在这里插入图片描述

看这个名字基本能猜到,这就是用来处理,Lifecycle的。除了传统的Aware接口之外,LifecycleProcessor还增加了onRefresh/onClose方法。这两是用于context刷新的close时候的通知。对于DefaultLifecycleProcessor来说,在这俩方法里面就可以做自动启动和停止所有的Cyclelife的Component。

具体的做法

  1. start方法

    1. 从beanFactory中获取所有实现实现了Lifecycle接口的bean。

    2. 增加了对SmartLifecycle的处理(是否自动启动)

    3. 此外还增加对Phased接口的处理,SmartLifeCycly实现了这个接口,如果没有实现默认的是就是0.

    4. 针对Phased接口分组,排序,将同一个Phased的bean放在一个LifecycleGroup里面。

    5. 封装成LifecycleGroup之后,因为LifecycleGroup里面是一组lifecycle的集合,所以,调用LifecycleGroup的start方法就是循环调 用LifecycleGroup里面集合的lifecycle的start方法。并且在LifecycleGroup里面记录了smartLifecycle的数量。

    6. 在调用之前,先调用当前bean依赖的bean的start方法。

    7. 在调用的时候增加了对自动启动和的支持。

    到这里,start方法就结束了。

  2. stop方法

    1. 从beanFactory中获取所有实现实现了Lifecycle接口的bean。

    2. 此外还增加对Phased接口的处理,SmartLifeCycly实现了这个接口,如果没有实现默认的是就是0.

    3. 针对Phased接口分组,排序,将同一个Phased的bean放在一个LifecycleGroup里面。

    4. 按照Phased的大小排序,倒叙。

    5. 封装成LifecycleGroup。然后循环调用。这里的调用得展开说说了

    6. 会通过smartLifecycle的数量,创建一个CountDownLatch。并且在创建一个线程安全的Set。

    7. 先调用当前bean依赖的bean的stop方法。

    8. 如果当前的bean 在运行,(Lifecycle#isRunning的返回值)

      1. 如果是smartLifecycle,就会将调用smartLifecycle的stop方法,并且传递一个callBack的Runnable。

        在这个callback里面主要是下面的代码

        ((SmartLifecycle) bean).stop(() -> {
                      // 利用countdown来做同步,
        							latch.countDown();
                // 将之前添加到countDownBeanNames里面的bean移除掉。
        							countDownBeanNames.remove(beanName);
        							if (logger.isDebugEnabled()) {
        								logger.debug("Bean '" + beanName + "' completed its stop procedure");
        							}
        						});
        
      2. 如果不是,直接调用Lifecycle的stop方法,

    9. 循环调用结束之后,直接调用latch.await(this.timeout, TimeUnit.MILLISECONDS);等待,刚才的同步操作。

问题?

  1. 同步怎么用?

    如果不实现stop(Runnable callback)方法,这个同步是没有意义的。必须要重写这个方法。才能使countdownLatch起作用,并且countdownLatch在异步的环境下才有作用,如果在一个单线程的话,这个是没有什么意义的。

  2. 这里为啥要有这个同步的操作。

    需要同步,就说明可能会有异步的操作,那么对于一个框架来说,提供的功能应该全面。此外,smartLifecycle在注释里面人家说清楚了,提供了异步的支持了。


public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {

   private final Log logger = LogFactory.getLog(getClass());
   // 超时时间。 单位是TimeUnit.MILLISECONDS。异步任务同步的等待时间,这是给每一个phase都起作用的
   private volatile long timeoutPerShutdownPhase = 30000;
   // 运行标志
   private volatile boolean running;
   // beanFactory
   @Nullable
   private volatile ConfigurableListableBeanFactory beanFactory;


   // 设置超时
   public void setTimeoutPerShutdownPhase(long timeoutPerShutdownPhase) {
      this.timeoutPerShutdownPhase = timeoutPerShutdownPhase;
   }

   @Override
   public void setBeanFactory(BeanFactory beanFactory) {
      if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
         throw new IllegalArgumentException(
               "DefaultLifecycleProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
      }
      this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
   }

   private ConfigurableListableBeanFactory getBeanFactory() {
      ConfigurableListableBeanFactory beanFactory = this.beanFactory;
      Assert.state(beanFactory != null, "No BeanFactory available");
      return beanFactory;
   }


   // Lifecycle implementation

  // 启动 所有已经注册到BeanFactory中的bean,这些bean实现了Lifecycle接口,
  // 对于实现了SmartLifecycle的接口,将会通过阶段这个对象来控制,阶段按照从小到大的顺序来排列。
  // 没有实现SmartLifecycle的接口,会采用默认值0,bean依赖其他的bean,在这个bean启动之前,先启动依赖的bean。
   @Override
   public void start() {
      // 这里的启动是启动所有,
      startBeans(false);
      this.running = true;
   }

   // 停止所有的bean
   // 也是按照阶段来分的,不过这里的顺序和上面的相反,从高到低。
  // 对于依赖也是和上面是同样的操作。先停止依赖的bean。
   @Override
   public void stop() {
      stopBeans();
      this.running = false;
   }
  
   // LifecycleProcessor接口的实现,在context refresh的时候,调用,和start方法一样,不过传递的参数不一样,
   @Override
   public void onRefresh() {
      startBeans(true); // 这里只是启动自动启动功能的bean
      this.running = true;
   }

   @Override
   public void onClose() {
      stopBeans();
      this.running = false;
   }

   @Override
   public boolean isRunning() {
      return this.running;
   }



   // autoStartupOnly表示是否只启动自动启动的类。
   private void startBeans(boolean autoStartupOnly) {
      // 从bean工厂中获取所有的Lifecycle的bean
      Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
     // key是阶段的返回值,value是LifecycleGroup。
      Map<Integer, LifecycleGroup> phases = new HashMap<>();
     // 开始遍历bean工厂中的lifeCycle的bean
      lifecycleBeans.forEach((beanName, bean) -> {
         // 如果不是自动启动,或者bean是SmartLifecycle,并且需要自动启动。
         if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            int phase = getPhase(bean); // 拿到这个bean的phase。就是Phased#getPhase的返回值。
            LifecycleGroup group = phases.get(phase); // 如果没有就创建,如果有,就直接添加。也就是说,LifecycleGroup是一组
                                                     // 相同phase的集合。
            if (group == null) {
               group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
               phases.put(phase, group);
            }
            group.add(beanName, bean);
         }
      });
     
     // 遍历,按照key的顺序,排序,调用
      if (!phases.isEmpty()) {
         List<Integer> keys = new ArrayList<>(phases.keySet());
         Collections.sort(keys);
         for (Integer key : keys) {
            // 注意,这个启动是启动一组Lifecycle。
            phases.get(key).start();
         }
      }
   }

  
  // 真正做做调用的地方。
  // lifecycleBeans 就是bean工厂中所有实现了Lifecycle的集合。
  // beanName要启动的bean的名字
  // autoStartupOnly是否要自动启动
   private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {    // 先移除
      Lifecycle bean = lifecycleBeans.remove(beanName);
     
      if (bean != null && bean != this) {
         // 依赖的bean
         String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
         for (String dependency : dependenciesForBean) {
           // 先调用依赖的bean的start方法
            doStart(lifecycleBeans, dependency, autoStartupOnly);
         }
        // 如果没有运行,并且 不是自动启动或者不是SmartLifecycle,或者是SmartLifecycle并且是自动启动的。
         if (!bean.isRunning() &&
               (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
            if (logger.isTraceEnabled()) {
               logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
            }
            try {
               // 直接启动
               bean.start();
            }
            catch (Throwable ex) {
               throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
            }
            if (logger.isDebugEnabled()) {
               logger.debug("Successfully started bean '" + beanName + "'");
            }
         }
      }
   }
    // 停止,不过这里的phases顺序是相反的。
   private void stopBeans() {
      Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
      Map<Integer, LifecycleGroup> phases = new HashMap<>();
      lifecycleBeans.forEach((beanName, bean) -> {
         int shutdownPhase = getPhase(bean);
         LifecycleGroup group = phases.get(shutdownPhase);
         if (group == null) {
            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) {
            phases.get(key).stop();
         }
      }
   }

   // 真正开始stop的地方
   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 {
            // bean如果是运行的
            if (bean.isRunning()) {
               if (bean instanceof SmartLifecycle) {
                  if (logger.isTraceEnabled()) {
                     logger.trace("Asking bean '" + beanName + "' of type [" +
                           bean.getClass().getName() + "] to stop");
                  }
                 // countDownBeanNames是smart的集合 
                  countDownBeanNames.add(beanName);
                 // 这是直接调用他的stop方法,并且传递了一个一段操作。
                  ((SmartLifecycle) bean).stop(() -> {
                     // countdowm 利用这种方式做同步
                     latch.countDown();
                     countDownBeanNames.remove(beanName);
                     if (logger.isDebugEnabled()) {
                        logger.debug("Bean '" + beanName + "' completed its stop procedure");
                     }
                  });
               }
               else {
                 // 如果不是smartLifecycle,就直接调用他的stop方法
                  if (logger.isTraceEnabled()) {
                     logger.trace("Stopping bean '" + beanName + "' of type [" +
                           bean.getClass().getName() + "]");
                  }
                  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);
            }
         }
      }
   }

   protected Map<String, Lifecycle> getLifecycleBeans() {
      ConfigurableListableBeanFactory beanFactory = getBeanFactory();
      Map<String, Lifecycle> beans = new LinkedHashMap<>();
      String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
      for (String beanName : beanNames) {
         String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
         boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
         String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
         if ((beanFactory.containsSingleton(beanNameToRegister) &&
               (!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
               matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
            Object bean = beanFactory.getBean(beanNameToCheck);
            if (bean != this && bean instanceof Lifecycle) {
               beans.put(beanNameToRegister, (Lifecycle) bean);
            }
         }
      }
      return beans;
   }

   private boolean matchesBeanType(Class<?> targetType, String beanName, BeanFactory beanFactory) {
      Class<?> beanType = beanFactory.getType(beanName);
      return (beanType != null && targetType.isAssignableFrom(beanType));
   }

  
   protected int getPhase(Lifecycle bean) {
      return (bean instanceof Phased ? ((Phased) bean).getPhase() : 0);
   }


   private class LifecycleGroup {
       // phase值
      private final int phase;
     // 等待时间
      private final long timeout;
     // beanfactory中Lifecycle的实现类
      private final Map<String, ? extends Lifecycle> lifecycleBeans;
     // 是否只启动自动启动的bean
      private final boolean autoStartupOnly;
     // 同一个节点的LifecycleGroupMember的集合
      private final List<LifecycleGroupMember> members = new ArrayList<>();
     // smartMemberCount的数量
      private int smartMemberCount;

      public LifecycleGroup(
            int phase, long timeout, Map<String, ? extends Lifecycle> lifecycleBeans, boolean autoStartupOnly) {

         this.phase = phase;
         this.timeout = timeout;
         this.lifecycleBeans = lifecycleBeans;
         this.autoStartupOnly = autoStartupOnly;
      }
      
     // 将对象添加到members里面。用LifecycleGroupMember包装。
      public void add(String name, Lifecycle bean) {
         this.members.add(new LifecycleGroupMember(name, bean));
         if (bean instanceof SmartLifecycle) {
           // 如果是smartLifeCycle,计数++ 
            // 这个++的目的是为了之后的创建countdownLatch,保证同步
            this.smartMemberCount++;
         }
      }

      public void start() {
         if (this.members.isEmpty()) {
            return;
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Starting beans in phase " + this.phase);
         }
         Collections.sort(this.members);
         for (LifecycleGroupMember member : this.members) {
            doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
         }
      }

      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 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(this.lifecycleBeans, member.name, latch, countDownBeanNames);
            }
            else if (member.bean instanceof SmartLifecycle) {
               // Already removed: must have been a dependent bean from another phase
               latch.countDown();
            }
         }
         try {
           // 当前的这个为啥在这里等地,
            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 + "ms: " + countDownBeanNames);
            }
         }
         catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
         }
      }
   }


   /**
    * Adapts the Comparable interface onto the lifecycle phase model.
    */
   private class LifecycleGroupMember implements Comparable<LifecycleGroupMember> {

      private final String name;

      private final Lifecycle bean;

      LifecycleGroupMember(String name, Lifecycle bean) {
         this.name = name;
         this.bean = bean;
      }
    
      // 话说,这个比较有意思吗?都同一个组了,这个phase不都是一样的吗?
      @Override
      public int compareTo(LifecycleGroupMember other) {
         int thisPhase = getPhase(this.bean);
         int otherPhase = getPhase(other.bean);
         return Integer.compare(thisPhase, otherPhase);
      }
   }
}

那么DefaultLifecycleProcessor在哪里调用的?还是之前的老办法?点看看调用的地方

调用

在这里插入图片描述

在AbstractApplicationContext里面调用,会在BeanFactory中检测bean的名字为lifecycleProcessor,如果没有就创建一个DefaultLifecycleProcessor。
在这里插入图片描述

initLifeCycleProcessor会在refresh方法里面调用。也就是在标准的启动流程里面,会调用。

在这里插入图片描述

先创建,在调用。调用LifecycleProcessor#onRefresh方法。从这里开始就会启动。走上面分析的SmartLifecycle的逻辑使用

使用

比如WebSocketConnectionManager
在这里插入图片描述

这个类主要是用来管理WebSocket

在start方法里面通过url来打开连接,在stop方法里面关闭

具体的可以在看看。

关于博客这件事,我是把它当做我的笔记,里面有很多的内容反映了我思考的过程,因为思维有限,不免有些内容有出入,如果有问题,欢迎指出。一同探讨。谢谢。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
elasticjob-lite-lifecycle 3.1.0 是一个轻量级分布式任务调度器的生命周期管理工具。它是 ElasticJob 的一个组件,可以帮助开发者更方便地管理任务的生命周期。 elasticjob-lite-lifecycle 3.1.0 提供了以下主要功能: 1. 任务的创建与注册:可以通过该工具创建任务并将其注册到 ElasticJob 中。开发者可以指定任务的名称、描述、执行模式等信息。 2. 任务的修改与更新:可以修改已注册的任务的属性,如任务的运行时间表达式、任务执行参数等。任何对任务的修改和更新都可以通过该工具进行。 3. 任务的启动与暂停:可以通过该工具对任务进行启动和暂停操作。当任务处于暂停状态时,任务调度器不会触发任务的执行。当任务处于启动状态时,任务调度器会按照设置的时间表达式来触发任务的执行。 4. 任务的删除与注销:可以通过该工具删除已创建的任务,并将其从 ElasticJob 中注销。注销后的任务将不再参与任务调度。 5. 任务的状态查询:可以查询任务的当前状态,包括是否处于启动状态、最近一次执行时间、下一次执行时间等。这些状态信息可以帮助开发者更好地监控任务的执行情况。 6. 任务的日志管理:可以通过该工具查看任务的执行日志,包括任务的执行结果、执行时间、日志级别等。这些日志信息可以帮助开发者分析任务的执行情况,排查问题。 elasticjob-lite-lifecycle 3.1.0 简化了任务的生命周期管理流程,提供了丰富的功能,使开发者可以更加方便地管理和监控任务。同时,它与 ElasticJob 的其他组件紧密结合,为分布式任务调度提供了全面的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值