public interface Lifecycle { void start(); void stop(); boolean isRunning(); }这个接口一共就三个方法:
isRunning:这个是返回组件是否已经处于运行状态了,对于容器来说,只有当容器中的所有适用组件都处于运行状态时,这个方法返回 true,否则返回 false。
@Component public class MyLifeCycle implements Lifecycle { private volatile boolean running; @Override public void start() { running = true; System.out.println("start"); } // 堆代码 duidaima.com @Override public void stop() { running = false; System.out.println("stop"); } @Override public boolean isRunning() { return running; } }需要自定义一个 running 变量,该变量用来描述当前组件是否处于运行/停止状态,因为系统在调用 start 和 stop 方法的时候,都会先调用 isRunning 方法,用以确认是否需要真的调用 start/stop 方法。
@Configuration @ComponentScan public class JavaConfig { }最后我们启动容器:
public class Demo { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class); ctx.start(); ctx.stop(); } }启动之后,我们就可以看到控制台打印出来的信息:
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; } }大家看一下,这里首先多了一个 isAutoStartup 方法,这个方法就表示是否自动执行 startup 方法,这个方法返回 true,则 startup 方法会被自动触发,这个方法要是返回 false,则 startup 方法就不会被自动触发(那么效果就等同于 LifeCycle 了)。
@Component public class MyLifeCycle implements SmartLifecycle { private volatile boolean running; @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; } @Override public boolean isAutoStartup() { return SmartLifecycle.super.isAutoStartup(); } @Override public void stop(Runnable callback) { stop(); callback.run(); } @Override public int getPhase() { return 0; } }
public interface LifecycleProcessor extends Lifecycle { void onRefresh(); void onClose(); }onRefresh:这个是在上下文刷新的时候被触发,例如在容器启动的时候这个方法被触发。
@Override public void onRefresh() { startBeans(true); this.running = true; } @Override public void onClose() { stopBeans(); this.running = false; }
private void startBeans(boolean autoStartupOnly) { Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); Map<Integer, LifecycleGroup> phases = new TreeMap<>(); lifecycleBeans.forEach((beanName, bean) -> { if (!autoStartupOnly || (bean instanceof SmartLifecycle smartLifecycle && smartLifecycle.isAutoStartup())) { int phase = getPhase(bean); phases.computeIfAbsent( phase, p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly) ).add(beanName, bean); } }); if (!phases.isEmpty()) { phases.values().forEach(LifecycleGroup::start); } }在这个方法中,首先调用 getLifecycleBeans 方法,这个方法的作用是去 Spring 容器中查找所有 Lifecycle 类型的 Bean,并把查找结果封装到一个 Map 集合中返回。接下来就去遍历这个 Map,遍历的时候由于 autoStartupOnly 变量传进来的时候是 true,取反之后就是 false 了,所以就会去判断这个 Bean 是否为 SmartLifecycle 类型,如果是该类型并且 isAutoStartup 方法返回 true,就表示要自动执行 start 方法。
public void start() { if (this.members.isEmpty()) { return; } Collections.sort(this.members); for (LifecycleGroupMember member : this.members) { doStart(this.lifecycleBeans, member.name, this.autoStartupOnly); } } private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) { Lifecycle bean = lifecycleBeans.remove(beanName); if (bean != null && bean != this) { String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName); for (String dependency : dependenciesForBean) { doStart(lifecycleBeans, dependency, autoStartupOnly); } if (!bean.isRunning() && (!autoStartupOnly || !(bean instanceof SmartLifecycle smartLifecycle) || smartLifecycle.isAutoStartup())) { bean.start(); } } }在 doStart 方法中,从集合中取出来 Lifecycle,然后查找一下该 Lifecycle 是否有依赖的 Bean,如果有,就继续递归调用 doStart 方法。否则,在 isRunning 返回 false(即该组件还没有运行),且 bean 不是 SmartLifecycle 类型(那就只能是 Lifecycle 类型)或者 bean 是 SmartLifecycle 类型且 isAutoStartup 方法为 true 的情况下,调用 bean 的 start 方法。
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(); } } }这块的逻辑跟 start 差不多,就是排序的方案有一些差别。这里用了 HashMap,没有用 TreeMap,然后在具体调用的时候,再去给 key 排序的。这里调用到的也是 LifecycleGroup 的 stop 方法,我们来看下:
public void stop() { if (this.members.isEmpty()) { return; } 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(); } }大家看一下,这里的 doStop 方法,最终就会触发到 Lifecycle 的 stop,这个里边的代码简单,我们就不去细看了。需要提醒大家的时候,这里使用到了这样一个计数器,初始值就是 members 的数量,每当调用一个 member 的 stop 方法之后,这个计数器减一,这样,到下面调用 await 的时候,就刚刚好不用等。
@Configuration @ComponentScan public class JavaConfig { @Bean DefaultLifecycleProcessor lifecycleProcessor() { DefaultLifecycleProcessor processor = new DefaultLifecycleProcessor(); processor.setTimeoutPerShutdownPhase(2000); return processor; } }上面这个案例中设置了超时时间为 2s。好啦,这就是关于 Lifecycle 的整体触发流程。接下来我们来看下自动触发和手动触发分别是在哪里触发的。
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. getLifecycleProcessor().onRefresh(); // Publish the final event. publishEvent(new ContextRefreshedEvent(this)); }这里有两个方法跟本文相关,一个是 initLifecycleProcessor,这个是初始化 LifecycleProcessor,就是去 Spring 容器中查找 LifecycleProcessor,找到就用,没找到就创建新的。然后就是 getLifecycleProcessor().onRefresh(); 方法,这个就是触发了 DefaultLifecycleProcessor#onRefresh 方法,而关于该方法的逻辑,我在前面已经介绍过了。
protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) { this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class); } else { DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor(); defaultProcessor.setBeanFactory(beanFactory); this.lifecycleProcessor = defaultProcessor; beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor); } }大家注意,LIFECYCLE_PROCESSOR_BEAN_NAME 常量的值是 lifecycleProcessor,为什么要强调这个,如果我们是自定义 DefaultLifecycleProcessor,那么 beanName 必须是 lifecycleProcessor,否则系统会以为我们没有自定义 DefaultLifecycleProcessor。
@Override public void start() { getLifecycleProcessor().start(); publishEvent(new ContextStartedEvent(this)); }相当于直接调用了 DefaultLifecycleProcessor 的 start 方法:
@Override public void start() { startBeans(false); this.running = true; }这个跟 DefaultLifecycleProcessor 的 onRefresh 方法内容基本一致,唯一的区别在于调用 startBeans 的时候,传入的参数为 false,这个参数带来的变化,这个我在前面的内容中已经分析过了,这里就不再啰嗦啦。