Spring IOC容器初始化后,執行一些邏輯操作的幾種實現方式
https://blog.csdn.net/lzb348110175/article/details/106071906
解析8種實現方式 使用介紹 1.實現ApplicationContextAware,重寫setApplicationContext()方法 2.實現InitializingBean,重寫afterPropertiesSet()方法 3. 在類中的方法上,添加@PostConstruct注解。(@PreDestroy注銷時使用) 4.類實現BeanPostProcessor接口,重寫postProcessBeforeInitialization()、postProcessAfterInitialization()方法 5.類實現 SmartLifecycle,重寫相關方法 6.實現ApplicationContextListener<ContextRefreshedEvent>,重寫onApplicationEvent()方法 7.類實現ApplicationRunner,重寫run()方法 8.類實現CommandLineRunner,重寫run()方法 寫在開篇 在項目的開發中,通常都會用到 Spring 來進行項目管理。在某些應用中,我們希望當Spring 容器將所有的 Bean 都初始化完成后,做一個操作(例如:將數據庫中的字典,加載到內存中)。那么如何在 Spring IOC 容器初始化完成后,自動觸發某個方法來完成某些業務邏輯配置相關的操作執行呢?一共能找到的介紹有如下7種,但是這7種還各自都有些不同之處。 解析8種實現方式 類實現ApplicationContextAware,重寫setApplicationContext()方法 類實現InitializingBean,重寫afterPropertiesSet()方法 在類中的方法上,添加@PostConstruct注解。(@PreDestroy注銷時使用) 類實現BeanPostProcessor,重寫postProcessBeforeInitialization()、postProcessAfterInitialization()方法 類實現 SmartLifecycle,重寫相關方法 類實現ApplicationContextListener,重寫onApplicationEvent()方法 類實現ApplicationRunner,重寫run()方法 類實現CommandLineRunner,重寫run()方法 說明: 第 1 、2 種方式,是在所有 bean 對象注冊到 IOC 容器完成之后,通過 后置處理器 或者Spring 啟動后的其他后置操作,來針對指定實現 ApplicationContextAware 或 InitializingBean 的一個bean類進行操作,達到配置全局的目的。比如說:將數據庫中的字典,加載到內存中 這種,並不需要每一個bean都配置的功能。(提示:說到底第1、2種方式,和本文提及的 Spring IOC 初始化后。還是有一些出入的,本文也就一並都放到這里介紹了) 第 3 種方式,和 Spring 的啟動流程無關,只和 Servlet 容器相關。(提示:Spring 項目在啟動 Servlet(此處以 Tomcat 為例)時,已經完成了 IOC 的相關操作,滿足本文題目在 Spring IOC 初始化后) 第 4 種方式,是對 Spring IOC 容器中每個bean對象的前置、后置增強。(提示:也和本文要求 Spring IOC 容器初始化后有出入。本文也就一並都放到這里介紹了)) 第 5 種方式,根據源碼我們了解到 LifecycleProcessor 處理器是在Spring 容器啟動最后一步 Last step: finishRefresh();這個方法中調用到的(提示:此時 Spring IOC 容器的初始化工作已經完成滿足本文題目在 Spring IOC 初始化后) 第 6 種方式,使用 ApplicationListener 監聽機制。監聽 ApplicationContextListener<ContextRefreshedEvent>的方式,Spring IOC 容器在所有的bean都初始化完成並被成功裝載后會觸發該事件(提示:監聽器方式 也可以滿足本文題目在 Spring IOC 初始化后,執行部分邏輯操作) 第 7、8 種方式,實現 ApplicationRunner、CommandLineRunner 接口的方式。都是在容器啟動完成的時執行。(提示:這種方式也可以滿足本文題目在 Spring IOC 初始化后,執行部分邏輯操作) 綜合來說: 只有3、5、6、7、8 這五種方式,是徹底在 Spring IOC容器初始化后,執行一些邏輯操作。其它三種方式只能說是變相滿足本文要求吧 使用介紹 1.實現ApplicationContextAware,重寫setApplicationContext()方法 實現ApplicationContextAware接口並重寫setApplicationContext()方法獲取ApplicationContext實例,這個要追溯到ApplicationContextAwareProcessor類。首先我們來看一下 ApplicationContextAwareProcessor 這個類,它是BeanPostProcessor(后置處理器)的一個實現類,此處附 Spring 啟動源碼來了解這個后置處理器。 此處源碼分析, 你可參考:Spring IOC 源碼解析一文學習更清晰。根據代碼,重點:在注冊后置處理器時,Spring IOC 容器已經初始化完成,所以我們可以通過這種方式,在 IOC 容器初始化后,執行一些邏輯操作。 @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); //1.此處 obtainFreshBeanFactory()方法,來完成Spring IOC容器的 定位、加載、注冊 等操作 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //2.此處用來注冊配置后置處理器(說明在配置后置處理器時,IOC容器已經創建完成) registerBeanPostProcessors(beanFactory); //省略部分源碼 } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); } finally { resetCommonCaches(); } } } 示例:(本例使用 Spring Boot框架) /** * TODO 實現 ApplicationContextAware 接口 * * @author liuzebiao * @Date 2020-5-12 15:34 */ @Component public class AfterIocInitialConfig implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { //在此處執行邏輯操作 System.out.println("在此執行一些邏輯操作"); } } 2.實現InitializingBean,重寫afterPropertiesSet()方法 (bean 配置文件屬性 init-method 用於在bean初始化時指定執行方法,可以用來替代繼承 InitializingBean接口) InitializingBean接口為bean提供了初始化方法的方式,它只包括afterPropertiesSet()方法,凡是繼承該接口的類,在初始化 bean 的時候都會執行該方法。(注意:重寫了InitializingBean的 bean 在初始化時才會執行,沒重寫的 bean 是不會被執行的) @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); //1.此處 obtainFreshBeanFactory()方法,來完成Spring IOC容器的 定位、加載、注冊 等操作 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // 省略部分代碼 // Instantiate all remaining (non-lazy-init) singletons. //2.初始化所有的單例 bean(實現InitializingBean,重寫afterPropertiesSet()方法,在此處執行) finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); //省略部分源碼 } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); } finally { resetCommonCaches(); } } } 示例:(本例使用 Spring Boot框架) /** * TODO 實現 InitializingBean 接口 * * @author liuzebiao * @Date 2020-5-12 15:34 */ @Component public class AfterIocInitialConfig implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { //在此處執行邏輯操作 System.out.println("在此執行一些邏輯操作"); } } 3. 在類中的方法上,添加@PostConstruct注解。(@PreDestroy注銷時使用) @PostConstruct 說明: 被 @PostConstruct 修飾的方法會在服務器加載 Servlet 的時候運行,並且只會被服務器調用一次,類似於 Servlet 的 init() 方法。被@PostConstruct 修飾的方法會在構造函數之后,init() 方法之前運行。 @PostConstruct 注釋用於在依賴關系注入完成之后需要執行的方法上,以執行任何初始化。此方法必須在將類放入服務之前調用。支持依賴關系注入的所有類都必須支持此注釋。即使類沒有請求注入任何資源,用@PostConstruct 注釋的方法也必須被調用。注意:只有一個方法可以用此注釋進行注釋。 @PreDestroy 說明: 被 @PreDestroy 修飾的方法會在服務器卸載 Servlet 的時候運行,並且只會被服務器調用一次,類似於 Servlet 的 destroy() 方法。被 @PreDestroy 修飾的方法會在 destroy() 方法之后運行,在 Servlet 被徹底卸載之前。 @PreDestroy 注釋作為回調通知用於各方法,以表示該實例正處於被容器移除的過程中。用 @PreDestroy 注釋的方法通常用於釋放它已經持有的資源,所有支持 @PostConstruct 的容器管理對象都必須支持此注釋 應用 @PostConstruct、@PreDestroy 注釋的方法必須遵守以下所有標准: 該方法不得有任何參數,除非是在EJB 攔截器(interceptor)的情況下,它可以帶有一個 InvocationContext 對象; 該方法的返回類型必須為 void; 該方法不得拋出已檢查異常; 應用@PostConstruct 的方法可以使 pulbic、protected、package private 或 private; 除了應用程序客戶端之外,該方法不能是 static;該方法可以是 final; 示例:(本例使用 Spring Boot框架) /** * TODO @PostConstruct、@PreDestroy注釋的使用 * * @author liuzebiao * @Date 2020-5-12 15:34 */ @Component public class AfterIocInitialConfig{ //在服務器加載 Servlet 的時候執行 @PostConstruct public void doSomething(){ //在此處執行邏輯操作 System.out.println("在此執行一些邏輯操作"); } //在服務器卸載 Servlet 的時候執行 @PreDestroy public void shutDownDoSomething(){ System.out.println("卸載Servlet時執行"); } } @PostConstruct 注解,顯然和 Spring IOC容器的啟動沒有多大關系,它只和 Servlet 容器的加載有關系。加載 Servlet 時, IOC 容器其實已經初始化完成。所以使用 @PostConstruct 注解,可以滿足 Spring IOC 容器初始化后,執行一些邏輯操作。 4.類實現BeanPostProcessor接口,重寫postProcessBeforeInitialization()、postProcessAfterInitialization()方法 BeanPostProcessor是 Spring IOC 容器給我們提供的一個擴展接口。注意:該接口會在 Spring IOC 容器的每一個 bean 初始化前、后做一些相關操作,記住是每一個!!!。接口聲明如下: public interface BeanPostProcessor { //bean初始化方法調用前被調用 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; //bean初始化方法調用后被調用 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; } 比如說當前 IOC 容器,有200個bean對象。那么這200個bean對象都會在初始化前、后來調用被重寫的postProcessBeforeInitialization()、postProcessAfterInitialization()方法,相當於是 bean 對象初始化的前置、后置增強。 示例:(本例使用 Spring Boot框架) /** * TODO @BeanPostProcessor注釋的使用 * * @author liuzebiao * @Date 2020-5-12 15:34 */ @Component public class AfterIocInitialConfig implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName);//當前要初始化的 beanName System.out.println(beanName + ":對象初始化前執行一些操作"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName +":對象初始化后執行一些操作"); return bean; } } 5.類實現 SmartLifecycle,重寫相關方法 本模塊內容,部分摘自:https://blog.csdn.net/catoop/article/details/71274561 在使用 Spring 開發時,我們都知道,所有 bean都交給 Spring IOC 容器來統一管理,其中包括每一個 bean 的加載和初始化。有時候,我們需要在 Spring 加載和初始化所有bean后,接着執行一些任務或者啟動需要的異步服務,這樣我們可以使用 SmartLifecycle 來做到。 SmartLifecycle 是一個接口,繼承自 Lifecycle(生命周期)、Phased(如果有多個實現 Liftcycle接口的類,通過getPhase()方法來確定執行先后順序)兩個接口。當 Spring 容器加載所有 bean 並完成初始化之后,會接着回調實現該接口的類中對應的方法(start()方法)。 LifecycleProcessor 處理器,在源碼中的執行位置,如下所示: @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); //省略 // Last step: publish corresponding event. // 重點:LifecycleProcessor 在此處被調用(繼續進入方法查看) finishRefresh(); } catch (BeansException ex) { //省略 } finally { resetCommonCaches(); } } } protected void finishRefresh() { // Initialize lifecycle processor for this context. // 重點1:為當前context初始化 LifecycleProcessor() initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. // 重點2:調用 lifecycleProcessor 的 onRefresh() 方法(如果我們定義了一個類,實現了 lifecycle 相關接口,則會在此處調用自定義的 onRefresh() 方法) getLifecycleProcessor().onRefresh(); // Publish the final event. // 事件機制發布(在下一種實現方式 ApplicationContextListener 中會涉及到) publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); } 如果IOC容器沒有 lifecycleProcessor,則會使用 DefaultLifecycleProcessor 類,此處附DefaultLifecycleProcessor 類源碼(省略部分源碼) public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware { private volatile long timeoutPerShutdownPhase = 30000; private volatile boolean running; /** * Specify the maximum time allotted in milliseconds for the shutdown of * any phase (group of SmartLifecycle beans with the same 'phase' value). * <p>The default value is 30 seconds. */ public void setTimeoutPerShutdownPhase(long timeoutPerShutdownPhase) { this.timeoutPerShutdownPhase = timeoutPerShutdownPhase; } /** * Start all registered beans that implement {@link Lifecycle} and are <i>not</i> * already running. Any bean that implements {@link SmartLifecycle} will be * started within its 'phase', and all phases will be ordered from lowest to * highest value. All beans that do not implement {@link SmartLifecycle} will be * started in the default phase 0. A bean declared as a dependency of another bean * will be started before the dependent bean regardless of the declared phase. */ @Override public void start() { startBeans(false); this.running = true; } /** * Stop all registered beans that implement {@link Lifecycle} and <i>are</i> * currently running. Any bean that implements {@link SmartLifecycle} will be * stopped within its 'phase', and all phases will be ordered from highest to * lowest value. All beans that do not implement {@link SmartLifecycle} will be * stopped in the default phase 0. A bean declared as dependent on another bean * will be stopped before the dependency bean regardless of the declared phase. */ @Override public void stop() { stopBeans(); this.running = false; } @Override public void onRefresh() { startBeans(true); this.running = true; } @Override public void onClose() { stopBeans(); this.running = false; } @Override public boolean isRunning() { return this.running; } } 示例:(本例使用 Spring Boot框架) /** * TODO SmartLifecycle 接口的使用 * * @author liuzebiao * @Date 2020-5-12 10:36 */ @Component public class AfterIocInitialConfig implements SmartLifecycle, ApplicationContextAware { private boolean isRunning = false; private ApplicationContext context = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } /** * 1. 我們主要在該方法中啟動任務或者其他異步服務,比如開啟MQ接收消息 * 2. 當上下文被刷新(所有對象已被實例化和初始化之后)時,將調用該方法,默認生命周期處理器將檢查每個SmartLifecycle對象的isAutoStartup()方法返回的布爾值。 * 如果為“true”,則該方法會被調用,而不是等待顯式調用自己的start()方法。 */ @Override public void start() { System.out.println("執行start()方法"); // 執行完其他業務后,可以修改 isRunning = true isRunning = true; } /** * 如果工程中有多個實現接口SmartLifecycle的類,則這些類的start的執行順序按getPhase方法返回值從小到大執行。 * 例如:1比2先執行,-1比0先執行。 stop方法的執行順序則相反,getPhase返回值較大類的stop方法先被調用,小的后被調用。 */ @Override public int getPhase() { // 默認為0 return 0; } /** * 根據該方法的返回值決定是否執行start方法。 * 返回true時start方法會被自動執行,返回false則不會。 */ @Override public boolean isAutoStartup() { // return false; return true; } /** * SmartLifecycle子類才有的方法,當isRunning方法返回true時,該方法才會被調用。 */ /*@Override public void stop(Runnable callback) { System.out.println("stop(Runnable)"); // 如果你讓isRunning返回true,需要執行stop這個方法,那么就不要忘記調用callback.run()。 // 否則在你程序退出時,Spring的DefaultLifecycleProcessor會認為你這個TestSmartLifecycle沒有stop完成,程序會一直卡着結束不了,等待一定時間(默認超時時間30秒)后才會自動結束。 // PS:如果你想修改這個默認超時時間,可以按下面思路做,當然下面代碼是springmvc配置文件形式的參考,在SpringBoot中自然不是配置xml來完成,這里只是提供一種思路。 // <bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"> // <!-- timeout value in milliseconds --> // <property name="timeoutPerShutdownPhase" value="10000"/> // </bean> callback.run(); isRunning = false; }*/ /** * 1. 只有該方法返回false時,start方法才會被執行。 * 2. 只有該方法返回true時,stop(Runnable callback)或stop()方法才會被執行。 */ @Override public boolean isRunning() { // 默認返回false return isRunning; } /** * 接口Lifecycle的子類的方法,只有非SmartLifecycle的子類才會執行該方法。<br/> * 1. 該方法只對直接實現接口Lifecycle的類才起作用,對實現SmartLifecycle接口的類無效。<br/> * 2. 方法stop()和方法stop(Runnable callback)的區別只在於,后者是SmartLifecycle子類的專屬。 */ @Override public void stop() { System.out.println("執行stop()方法"); isRunning = false; } } 6.實現ApplicationContextListener<ContextRefreshedEvent>,重寫onApplicationEvent()方法 ApplicationContextListener 事件機制是觀察者設計模式的實現,通過ApplicationEvent類和ApplicationListener接口,可以實現ApplicationContext事件處理;如果容器中存在 ApplicationListener 的Bean,當 ApplicationContext 調用 publishEvent 方法時,對應的Bean會被觸發。publishEvent() 方法,同剛剛介紹的 Lifecycle 類似,也是在 finishRefresh() 方法中調用的。如下所示: protected void finishRefresh() { // Initialize lifecycle processor for this context. initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh(); // Publish the final event. // 重點:事件機制發布(在下一種實現方式 ApplicationContextListener 中會涉及到) publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); } 其中 Spring 有一些內置的事件,當完成某種操作時會發出某些事件動作。比如監聽ContextRefreshedEvent事件,當所有的bean都初始化完成並被成功裝載后會觸發該事件,實現ApplicationListener<ContextRefreshedEvent>接口可以收到監聽動作,然后可以寫自己的邏輯。同樣事件我們可以自定義、監聽也可以自定義,完全根據自己的業務邏輯來處理。 Spring內置事件 描述 ContextRefreshedEvent ApplicationContext 被初始化或刷新時,該事件被觸發。這也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法來發生。此處的初始化是指:所有的Bean被成功裝載,后處理Bean被檢測並激活,所有Singleton Bean 被預實例化,ApplicationContext容器已就緒可用 ContextStartedEvent 當使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法啟動 ApplicationContext 時,該事件被發布。你可以調查你的數據庫,或者你可以在接受到這個事件后重啟任何停止的應用程序。 ContextStoppedEvent 當使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 時,發布這個事件。你可以在接受到這個事件后做必要的清理的工作。 ContextClosedEvent 當使用 ConfigurableApplicationContext 接口中的 close() 方法關閉 ApplicationContext 時,該事件被發布。一個已關閉的上下文到達生命周期末端;它不能被刷新或重啟。 RequestHandledEvent 這是一個 web-specific 事件,告訴所有 bean HTTP 請求已經被服務。只能應用於使用DispatcherServlet的Web應用。在使用Spring作為前端的MVC控制器時,當Spring處理用戶請求結束后,系統會自動觸發該事件。 示例:(本例使用 Spring Boot框架) /** * TODO ApplicationListener 接口的使用 * * @author liuzebiao * @Date 2020-5-12 15:34 */ @Component public class AfterIocInitialConfig implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("監聽到所有的bean都已經初始化完成"); } } 附錄: 我們可以監聽 ServletWebServerInitializedEvent 類,來監聽 Servlet 是否初始化完成; 也可以監聽 ApplicationReadyEvent 類,來監聽應用(項目)是否啟動完成。 etc. 7.類實現ApplicationRunner,重寫run()方法 在開發中可能會有這樣的情景。需要在容器啟動的時候執行一些內容。比如讀取配置文件,數據庫連接之類的。Spring 項目中,我們可以通過實現 ApplicationRunner接口,重寫run() 方法。它的執行時機為容器啟動完成的時候。 示例:(本例使用 Spring Boot框架) /** * TODO ApplicationRunner 接口的使用 * * @author liuzebiao * @Date 2020-5-12 15:34 */ @Component public class AfterIocInitialConfig implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("當前項目已經啟動完成"); } } 8.類實現CommandLineRunner,重寫run()方法 SpringBoot 中額外給我們提供了一個接口,這個接口是 CommandLineRunner。它和 ApplicationRunner功能一樣,也都需要重寫run()方法。該接口也是在容器啟動完成的時候執行。 它們的不同之處在於:(其它使用都相同) ApplicationRunner 可以在 Spring、SpringBoot 項目中使用;CommandLineRunner 只能在 Spring Boot 中使用 ApplicationRunner 中 run() 方法的參數為 ApplicationArguments,而 CommandLineRunner 中 run() 方法的參數為 String數組。 示例:(本例使用 Spring Boot框架) /** * TODO CommandLineRunner 接口的使用 * * @author liuzebiao * @Date 2020-5-12 15:34 */ @Component public class AfterIocInitialConfig implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("當前項目已經啟動完成"); } }
_________________________________________________________________________________________________
當springMVC 容器初始化完成后執行某個方法
在某些應用中,我們希望,當spring 容器將所有的bean都初始化完成后,做一個操作(例如:將數據庫中的字典,加載到內存中),這時我們可以實現一個接口,如下:
- package com.yk.test.executor.processor
- public class InstantiationTracingBeanPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
- @Resource
- private MsEmailService msgEmailService;
- @Override
- public void onApplicationEvent(ContextRefreshedEvent event) {
- //需要執行的邏輯代碼,當spring容器初始化完成后就會執行該方法。
- }
- }
同時實例化該bean:
- <!-- 當Spring容器啟動完成后執行下面的這個Bean -->
- <bean class="com.yk.test.executor.processor.InstantiationTracingBeanPostProcessor"/>
但是這個時候,會存在一個問題,在web 項目中(spring mvc),系統會存在兩個容器,一個是root application context ,另一個就是我們自己的 projectName-servlet context(作為root application context的子容器)。
這種情況下,就會造成onApplicationEvent方法被執行兩次。為了避免上面提到的問題,我們可以只在root application context初始化完成后調用邏輯代碼,其他的容器的初始化完成,則不做任何處理,修改后代碼
如下:
- @Override
- public void onApplicationEvent(ContextRefreshedEvent event) {
- if(event.getApplicationContext().getParent() == null){//root application context 沒有parent,他就是老大.
- //需要執行的邏輯代碼,當spring容器初始化完成后就會執行該方法。
- }
- }