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