前言
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方法,用於結束生命周期之前的收尾業務邏輯處理;並且可以設置是否在容器刷新時自動開啟生命周期