springboot2啟動時(shí)執(zhí)行,初始化(或定時(shí)任務(wù))servletContext問題
springboot2啟動時(shí)執(zhí)行,初始化(或定時(shí)任務(wù))servletContext
需求:springboot 啟動后自動執(zhí)行,初始化數(shù)據(jù),并將數(shù)據(jù)放到 servletContext 中。
首先,不可使用 ServletContextListener 即不能用 @WebListener ,因?yàn)?servlet 容器初始化后,spring 并未初始化完畢,不能使用 @Autowired 注入 spring 的對象。
代碼如下:
可以實(shí)現(xiàn) ApplicationListener
@Component
public class SettingDataInitListener implements ApplicationListener<ContextRefreshedEvent> {
? ? @Override
? ? public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
? ? ? ? WebApplicationContext webApplicationContext =?
? ? ? ? ? ? (WebApplicationContext)contextRefreshedEvent.getApplicationContext();
? ? ? ? ServletContext servletContext = webApplicationContext.getServletContext();
? ? ? ? servletContext.setAttribute("key", "value");
? ? }
}使用注解注入
service類里注入 servletContext
@Autowired private ServletContext servletContext;
service類里要啟動執(zhí)行的方法加上注解
@PostConstruct
在定時(shí)任務(wù)里,也可以注入 servletContext,進(jìn)行定時(shí)操作
@Component
public class MyTask {
? ? @Autowired
? ? private ServletContext servletContext;
? ? // 秒 分 時(shí) 日 月 周
? ? @Scheduled(cron = "0 * * * * *")
? ? public void resetDays() {
? ? ? ? // servletContext
? ? }
}springboot啟動時(shí)初始化數(shù)據(jù)的幾種方式
在我們用springboot搭建項(xiàng)目的時(shí)候,經(jīng)常碰到在項(xiàng)目啟動時(shí)初始化一些字典數(shù)據(jù)、地市數(shù)據(jù)、等各類需求,針對這種需求Spring與Spring boot為我們提供了以下幾種方案供我們選擇:
- springboot提供的ApplicationRunner與CommandLineRunner接口
- Spring Bean初始化的init-method、PostConstruct注解、
InitializingBean、BeanPostProcessor接口
Spring的事件機(jī)制: 實(shí)現(xiàn) ApplicationListener 接口
一、ApplicationRunner與CommandLineRunner
如果需要在SpringApplication啟動時(shí)執(zhí)行一些特殊的代碼,可以通過實(shí)現(xiàn)ApplicationRunner或CommandLineRunner接口,這兩個(gè)接口都提供單一的run方法,且run方法僅在SpringApplication.run(…)完成之前調(diào)用。
區(qū)別:參數(shù)不一樣,CommandLineRunner的參數(shù)是最原始的參數(shù),沒有進(jìn)行任何處理,ApplicationRunner的參數(shù)是ApplicationArguments
ApplicationRunner接口只需要自己創(chuàng)建類實(shí)現(xiàn)ApplicationRunner接口
/**
?* @author 重慶阿湯哥
?* @Description: 測試
?* @date 2021/11/26 ?
?*/
@Component
@Slf4j
public class ApplicationRunnerTest implements ApplicationRunner {
? ? @Override
? ? public void run(ApplicationArguments args) throws Exception {
? ? ? ? log.info("ApplicationRunner init data.....");
? ? }
}CommandLineRunner
對于這個(gè)接口而言,我們可以通過Order注解或者使用Ordered接口來指定調(diào)用順序,@Order()中的值越小,優(yōu)先級越高
/**
?* @author 重慶阿湯哥
?* @Description: 測試
?* @date 2021/11/26 ?
?*/
@Component
@Slf4j
@Order(1)
public class CommandLineRunnerTest implements CommandLineRunner {
? ? @Override
? ? public void run(String... args) throws Exception {
? ? ? ? log.info("CommandLineRunner init data.....");
? ? }
}二、Spring Bean初始化的InitializingBean,init-method和PostConstruct
InitializingBean接口、BeanPostProcessor接口
InitializingBean接口為bean提供了初始化方法的方式,它只包括afterPropertiesSet()方法。
在spring初始化bean的時(shí)候,如果bean實(shí)現(xiàn)了InitializingBean接口,在對象的所有屬性被初始化后之后才會調(diào)用afterPropertiesSet()方法
/**
?* @author 重慶阿湯哥
?* @Description: 測試
?* @date 2021/11/26 ?
?*/
@Component
@Slf4j
@Component
public class InitialingzingBeanTest implements InitializingBean {
? ? @Override
? ? public void afterPropertiesSet() throws Exception {
? ? ? ?log.info("InitializingBean init....");
? ? }
}@PostConstruct
/**
?* @author 重慶阿湯哥
?* @Description: 測試
?* @date 2021/11/26 ?
?*/
@Component
@Slf4j
public class DynamicRouteMonitor {
? ?
? ? @PostConstruct
? ? public void init() {
? ? ? ? log.info("gateway route init...");
? ? ? ? }
}BeanPostProcessor接口
可以用于判斷某些特定類加載完成后才能初始化數(shù)據(jù)的場景,只需要自己實(shí)現(xiàn)該接口中的方法進(jìn)行前置條件判斷
public interface BeanPostProcessor {
? ? @Nullable
? ? default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
? ? ? ? return bean;
? ? }
? ? @Nullable
? ? default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
? ? ? ? return bean;
? ? }
}三、Spring的事件機(jī)制
在Spring中,默認(rèn)對ApplicationEvent事件提供了如下支持:
ContextStartedEvent:ApplicationContext啟動后觸發(fā)的事件ContextStoppedEvent:ApplicationContext停止后觸發(fā)的事件ContextRefreshedEvent:ApplicationContext初始化或刷新完成后觸發(fā)的事件;也就是容器初始化完成后調(diào)用。ContextClosedEvent:ApplicationContext關(guān)閉后觸發(fā)的事件;如web容器關(guān)閉時(shí)自動會觸發(fā)spring容器的關(guān)閉。甚至大家聽說過的鉤子程序都是調(diào)用ctx.registerShutdownHook()進(jìn)行注冊虛擬機(jī)關(guān)閉。
利用ContextRefreshedEvent事件進(jìn)行初始化操作
/**
?* @author 重慶阿湯哥
?* @Description:容器初始化完整后初始字典數(shù)據(jù)
?* @date 2021/11/26 ?10:51
?*/
@Component
public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent> {
? ? public void onApplicationEvent(ContextRefreshedEvent event) {
? ? ? ? //在容器加載完畢后獲取dao層來操作數(shù)據(jù)庫
? ? ? ? ISysDictTypeService sysDictTypeService = (ISysDictTypeService) event.getApplicationContext().getBean(ISysDictTypeService.class);
? ? ? ? sysDictTypeService.initDict();
? ? ? ? IProvCityService provCityService = (IProvCityService) event.getApplicationContext().getBean(IProvCityService.class);
? ? ? ? provCityService.initProvCity();
? ? }
? ? @Override
? ? protected Object clone() throws CloneNotSupportedException {
? ? ? ? return super.clone();
? ? }
}這幾種方式都可以滿足我們?nèi)粘i_發(fā)的需求,針對具體場景使用對應(yīng)的方案,在微服務(wù)應(yīng)用中使用也較廣泛。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于如何搭建CAS服務(wù)并將CAS項(xiàng)目導(dǎo)入IDEA
這篇文章主要介紹了關(guān)于如何搭建CAS服務(wù)并將CAS項(xiàng)目導(dǎo)入IDEA的問題,文中提供了詳細(xì)的圖文講解,需要的朋友可以參考下,如果有錯(cuò)誤的地方還請指正2023-03-03
詳解Java動態(tài)代理的實(shí)現(xiàn)及應(yīng)用
這篇文章主要介紹了詳解Java動態(tài)代理的實(shí)現(xiàn)及應(yīng)用的相關(guān)資料,希望通過本文大家能理解掌握J(rèn)ava動態(tài)代理的使用方法,需要的朋友可以參考下2017-09-09
spring boot+spring cache實(shí)現(xiàn)兩級緩存(redis+caffeine)
這篇文章主要介紹了spring boot+spring cache實(shí)現(xiàn)兩級緩存(redis+caffeine),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02
Spring6.x對調(diào)度和異步執(zhí)行的注解支持示例詳解
這篇文章主要為大家介紹了Spring6.x對調(diào)度和異步執(zhí)行的注解支持示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
如何實(shí)現(xiàn)Spring?Event(異步事件)
這篇文章主要介紹了如何實(shí)現(xiàn)Spring?Event(異步事件)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
詳解Spring中使用xml配置bean的細(xì)節(jié)
本篇文章主要介紹了Spring中使用xml配置bean的細(xì)節(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06

