spring中實現(xiàn)容器加載完成后再執(zhí)行自己的方法
spring容器加載完成后再執(zhí)行自己的方法
在開發(fā)過程中遇到了要在項目啟動后自動開啟某個服務(wù),由于使用了spring,我在使用了spring的 listener ,它有 onApplicationEvent ()方法, 在Spring容器將所有的Bean都初始化完成之后,就會執(zhí)行該方法 。
應(yīng)用場景
很多時候我們想要在某個類加載完畢時干某件事情,但是使用了spring管理對象,我們這個類引用了其他類(可能是更復(fù)雜的關(guān)聯(lián)),所以當我們?nèi)ナ褂眠@個類做事情時發(fā)現(xiàn)包空指針錯誤,這是因為我們這個類有可能已經(jīng)初始化完成,但是引用的其他類不一定初始化完成,所以發(fā)生了空指針錯誤
解決方案如下
1.寫一個類繼承spring的ApplicationListener監(jiān)聽,并監(jiān)控ContextRefreshedEvent事件(容易初始化完成事件)
2.定義簡單的bean:<bean id="startListener" class="com.itsm.core.service.table.StartListener"></bean> 或者直接使用@Service注解方式
@Service public class StartListener implements ApplicationListener<ContextRefreshedEvent> { ? ? public static final Map<Integer, TableMapper> mappers = new HashMap<>(); ? ? @Resource ? ? A_Mapper a_mapper; ? ? @Override ? ? public void onApplicationEvent(ContextRefreshedEvent event) ? ? { ? ? ? ? if(event.getApplicationContext().getParent() == null)//root application context 沒有parent,他就是老大. ? ? ? ? { ? ? ? ? ? ? //需要執(zhí)行的邏輯代碼,當spring容器初始化完成后就會執(zhí)行該方法。 ? ? ? ? ? ? System.out.println("\n\n\n\n\n______________\n\n\n加載了\n\n_________\n\n"); ? ? ? ? } ? ? ? ? //或者下面這種方式 ? ? ? ? if(event.getApplicationContext().getDisplayName().equals("Root WebApplicationContext")) ? ? ? ? { ? ? ? ? ? ? System.out.println("\n\n\n_________\n\n加載一次的 \n\n ________\n\n\n\n"); ? ? ? ? } ? ? ? ? mappers.put(1,a_mapper); ? ? } }
spring容器加載完成之后進行開啟一個線程進行數(shù)據(jù)更新操作
需求:最近做項目遇到了一個需求,數(shù)據(jù)表中有些數(shù)據(jù)需要定時更新,這樣就需要啟動一個線程完成,不想再新建一個項目來完成這些事,就想在spring啟動之后來開啟一個線程定時來完成這件事 ,直接上代碼
package com.irisian.picturelabel.listener; import com.irisian.picturelabel.service.PictureService; import com.irisian.picturelabel.service.TaskService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** ?* Author:吳滿心 ?* Date:2018/5/18 ?* Function:負責(zé)在spring容器加載完成之后進行圖片和任務(wù)數(shù)據(jù)表的更新 ?*/ @Component public class SpringFinishedListener implements InitializingBean { ? ? private static final Logger logger = LoggerFactory.getLogger(SpringFinishedListener.class); ? ? @Autowired ? ? private PictureService pictureService; ? ? @Autowired ? ? private TaskService taskService; ? ? @Override ? ? public void afterPropertiesSet() throws Exception { ? ? ? ? new Thread(() -> { ? ? ? ? ? ? while (true) { ? ? ? ? ? ? ? ? logger.info("開始執(zhí)行圖片和任務(wù)的更新操作!"); ? ? ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? ? ? pictureService.updatePictureStatus(); ? ? ? ? ? ? ? ? ? ? //更新任務(wù)的完成狀態(tài)信息 ? ? ? ? ? ? ? ? ? ? taskService.updateFinishStatus(); ? ? ? ? ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? ? ? logger.error(e.getMessage()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? ? ? Thread.sleep(1800000); ? ? ?//30分鐘執(zhí)行一次進行數(shù)據(jù)更新 ? ? ? ? ? ? ? ? } catch (InterruptedException e) { ? ? ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? ? ? logger.error(e.getMessage()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }).start(); ? ? } }
開始還嘗試過servlet的方法,如
package com.irisian.picturelabel.servlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; /** ?* Author:吳滿心 ?* Date:2018/5/18 ?* Function: ?*/ @WebServlet(name = "backServlet", urlPatterns = {"/backServlet"}) public class BackServlet extends HttpServlet { ? ? private static final Logger logger= LoggerFactory.getLogger(BackServlet.class); ? ? @Override ? ? public void init() throws ServletException { ? ? ? ? new Thread(()->{ ? ? ? ? ? ? while(true){ ? ? ? ? ? ? ? ? logger.info("我5秒鐘執(zhí)行一次"); ? ? ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? ? ? Thread.sleep(5000); ? ? ? ? ? ? ? ? } catch (InterruptedException e) { ? ? ? ? ? ? ? ? ? ? logger.error(e.getMessage()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }).start(); ? ? } ? ? @Override ? ? public void destroy() { ? ? ? ? logger.info("服務(wù)器關(guān)閉了"); ? ? } }
配置Configuration
package com.irisian.picturelabel.configuration; import com.irisian.picturelabel.exception.MyExceptionResolver; import com.irisian.picturelabel.servlet.BackServlet; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerExceptionResolver; /** ?* Author:吳滿心 ?* Date:2018/5/15 ?* Function: ?*/ @Configuration public class SpringConfiguration { ? ? @Bean ? ? public HandlerExceptionResolver getHandlerExceptionResolver() { ? ? ? ? return new MyExceptionResolver(); ? ? } ? ? /** ? ? ?* 配置一個后臺運行的servlet ? ? ?* @return ? ? ?*/ ? ? @Bean ? ? public ServletRegistrationBean servletRegistrationBean() { ? ? ? ? ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new BackServlet(), "/backServlet"); ? ? ? ? servletRegistrationBean.setLoadOnStartup(1); ? ? ? ?//數(shù)字越小,啟動優(yōu)先級越高,但是必須大于0 ? ? ? ? return servletRegistrationBean; ? ? } }
但是不滿足spring啟動之后,spring不啟動完成,就無法使用bean了,所以就按照前面的一種方法了
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot中使用Filter實現(xiàn)Header認證詳解
這篇文章主要介紹了Springboot中使用Filter實現(xiàn)Header認證詳解,當在?web.xml?注冊了一個?Filter?來對某個?Servlet?程序進行攔截處理時,它可以決定是否將請求繼續(xù)傳遞給?Servlet?程序,以及對請求和響應(yīng)消息是否進行修改,需要的朋友可以參考下2023-08-08