zoukankan      html  css  js  c++  java
  • 通过源码查看Spring SmartLifecycle 的执行顺序

         最新需要用到SmartLifecycle ,写了一个测试类,打印了一下执行顺序如下:

    /**
     * 
     * 
     * @author cuiyt
     * @date: 2017年8月31日 上午8:47:54
     */
    public class TestSmartLifecycle implements SmartLifecycle {
    
        private boolean isRunning = false;
        @Override
        public void start() {
            System.out.println("test start-------------------------");
            isRunning = true;
        }
    
        @Override
        public void stop() {
            System.out.println("test stop-------------------------");
            isRunning = false;
            
        }
    
        @Override
        public boolean isRunning() {
            System.out.println("test isRunning-------------------------");
            return isRunning;
        }
    
        @Override
        public int getPhase() {
            System.out.println("test getPhase-------------------------");
            return 0;
        }
    
        @Override
        public boolean isAutoStartup() {
            System.out.println("test isAutoStartup-------------------------");
            return true;
        }
    
        @Override
        public void stop(Runnable callback) {
            System.out.println("test callback-------------------------");
            isRunning = false;
        }
    
    }

    启动顺序


    停止顺序


    先来看启动顺序为什么执行了两次

    test isAutoStartup-------------------------
    test getPhase-------------------------

    private void startBeans(boolean autoStartupOnly) {
            Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();//获取Lifecycle实现类的bean
            Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
            for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
                Lifecycle bean = entry.getValue();//判断是不是自动启动,这里调用了isAutoStartup
                if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
                    int phase = getPhase(bean);//getPhase()方法内部调用了getPhase return (bean instanceof Phased ? ((Phased) bean).getPhase() : 0);
                    LifecycleGroup group = phases.get(phase);
                    if (group == null) {//如果相同启动顺序的不存在,则新new一个组,并将bean加入到这个组
                        group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                        phases.put(phase, group);
                    }
                    group.add(entry.getKey(), bean);//如果相同启动顺序的存在,则将bean加入到这个组
    }
         }
         if (phases.size() > 0) {

            List<Integer> keys = new ArrayList<Integer>(phases.keySet());
            Collections.sort(keys);
            for (Integer key : keys) {
              phases.get(key).start();//获取所有Lifecyccle并分完组后,则开始真正的执行
          }
        }

    接下来看执行的顺序

    test getPhase-------------------------
    test isRunning-------------------------
    test isAutoStartup-------------------------
    test start-------------------------

    public void start() {
                if (this.members.isEmpty()) {
                    return;
                }
                if (logger.isInfoEnabled()) {
                    logger.info("Starting beans in phase " + this.phase);
                }
                Collections.sort(this.members);//这里进行了排序,查看LifecycleGroupMember的源码(见下面代码),发现他实现了Comparable接口,compareTo方法里面再次调用了getPhase()
          for (LifecycleGroupMember member : this.members) { 
        
              if (this.lifecycleBeans.containsKey(member.name)) {
                  doStart(
    this.lifecycleBeans, member.name, this.autoStartupOnly); //调用doStart()
              }
          } }
        /**
         * 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;
            }
    
            @Override
            public int compareTo(LifecycleGroupMember other) {
                int thisOrder = getPhase(this.bean);
                int otherOrder = getPhase(other.bean);
                return (thisOrder == otherOrder ? 0 : (thisOrder < otherOrder) ? -1 : 1);
            }
        }

    doStart()

    /**
         * Start the specified bean as part of the given set of Lifecycle beans,
         * making sure that any beans that it depends on are started first.
         * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
         * @param beanName the name of the bean to start
         */
        private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
            Lifecycle bean = lifecycleBeans.remove(beanName);
            if (bean != null && !this.equals(bean)) {
                String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName);
                for (String dependency : dependenciesForBean) {
                    doStart(lifecycleBeans, dependency, autoStartupOnly);
                }
            //这里判断是否在运行,调用了
    isRunning(),isAutoStartup()
          if (!bean.isRunning() && (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) { 
            
    if (logger.isDebugEnabled()) {
              logger.debug(
    "Starting bean '" + beanName + "' of type [" + bean.getClass() + "]");
            }
            
            try {
              bean.start(); //调用start()
            }
    catch (Throwable ex) { throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex); } if (logger.isDebugEnabled()) { logger.debug("Successfully started bean '" + beanName + "'"); } } } }

    停止顺序

    test getPhase-------------------------
    2017-08-31 09:06:57.581 INFO 11028 --- [on(2)-127.0.0.1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0
    test getPhase-------------------------
    test isRunning-------------------------
    test callback-------------------------

    同样是先获取实现bean,并分组,调用了两次getPhase()

        private void stopBeans() {
            Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
            Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
            for (Map.Entry<String, Lifecycle> entry : lifecycleBeans.entrySet()) {
                Lifecycle bean = entry.getValue();
                int shutdownOrder = getPhase(bean);//第一次getPhase()
                LifecycleGroup group = phases.get(shutdownOrder);
                if (group == null) {
                    group = new LifecycleGroup(shutdownOrder, this.timeoutPerShutdownPhase, lifecycleBeans, false);
                    phases.put(shutdownOrder, group);
                }
                group.add(entry.getKey(), bean);
            }
            if (phases.size() > 0) {
                List<Integer> keys = new ArrayList<Integer>(phases.keySet());
                Collections.sort(keys, Collections.reverseOrder());
                for (Integer key : keys) {
                    phases.get(key).stop();//开始停止
                }
            }
        }

    stop方法

    public void stop() {
                if (this.members.isEmpty()) {
                    return;
                }
                if (logger.isInfoEnabled()) {
                    logger.info("Stopping beans in phase " + this.phase);
                }
                Collections.sort(this.members, Collections.reverseOrder());//排序调用了一次getPhase()
          CountDownLatch latch = new CountDownLatch(this.smartMemberCount); 
          Set
    <String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<String>());
        
          for (LifecycleGroupMember member : this.members) {
            
    if (this.lifecycleBeans.containsKey(member.name)) {
                doStop(
    this.lifecycleBeans, member.name, latch, countDownBeanNames); //调用doStop方法
            }
    else if (member.bean instanceof SmartLifecycle) {
      
                // already removed, must have been a dependent latch.countDown(); } }
              
    try { latch.await(this.timeout, TimeUnit.MILLISECONDS);
            
                if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isWarnEnabled()) {
                       logger.warn(
    "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()

    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 = this.beanFactory.getDependentBeans(beanName);
                for (String dependentBean : dependentBeans) {
                    doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames);
                }
                try {
                    if (bean.isRunning()) {//判断是都还在运行,调用了isRunning()

    if (bean instanceof SmartLifecycle) { if (logger.isDebugEnabled()) { logger.debug("Asking bean '" + beanName + "' of type [" + bean.getClass() + "] to stop"); } countDownBeanNames.add(beanName); ((SmartLifecycle) bean).stop(new Runnable() {//调用了stop(Runnable callback) 
    @Override
    public void run() { latch.countDown(); countDownBeanNames.remove(beanName); if (logger.isDebugEnabled()) { logger.debug("Bean '" + beanName + "' completed its stop procedure"); } } }); } else { if (logger.isDebugEnabled()) { logger.debug("Stopping bean '" + beanName + "' of type [" + bean.getClass() + "]"); } 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); } } } }
  • 相关阅读:
    创建线程的方式三:实现Callable接口 --- JDK 5.0新增
    线程的通信
    多线程的实例练习:银行账户双储户问题
    解决线程安全问题的方式三:Lock锁 --- JDK5.0新增
    演示线程的死锁问题
    Synchronized的各场景使用方法(多窗口售票例子接上篇)
    线程的【生命周期】和【线程的同步】(下面有多窗口售票例子)
    多线程:继承方式和实现方式的联系与区别
    创建多线程的方式二:实现Runnable接口
    Java项目生成可执行jar包、exe文件以及在Windows下的安装文件
  • 原文地址:https://www.cnblogs.com/cuyt/p/7456718.html
Copyright © 2011-2022 走看看