spring中实现容器加载完成后再执行自己的方法
阿文_ing 人气:0spring容器加载完成后再执行自己的方法
在开发过程中遇到了要在项目启动后自动开启某个服务,由于使用了spring,我在使用了spring的 listener ,它有 onApplicationEvent ()方法, 在Spring容器将所有的Bean都初始化完成之后,就会执行该方法 。
应用场景
很多时候我们想要在某个类加载完毕时干某件事情,但是使用了spring管理对象,我们这个类引用了其他类(可能是更复杂的关联),所以当我们去使用这个类做事情时发现包空指针错误,这是因为我们这个类有可能已经初始化完成,但是引用的其他类不一定初始化完成,所以发生了空指针错误
解决方案如下
1.写一个类继承spring的ApplicationListener监听,并监控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,他就是老大. { //需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。 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容器加载完成之后进行开启一个线程进行数据更新操作
需求:最近做项目遇到了一个需求,数据表中有些数据需要定时更新,这样就需要启动一个线程完成,不想再新建一个项目来完成这些事,就想在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:负责在spring容器加载完成之后进行图片和任务数据表的更新 */ @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("开始执行图片和任务的更新操作!"); try { pictureService.updatePictureStatus(); //更新任务的完成状态信息 taskService.updateFinishStatus(); } catch (Exception e) { e.printStackTrace(); logger.error(e.getMessage()); } try { Thread.sleep(1800000); //30分钟执行一次进行数据更新 } 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秒钟执行一次"); try { Thread.sleep(5000); } catch (InterruptedException e) { logger.error(e.getMessage()); } } }).start(); } @Override public void destroy() { logger.info("服务器关闭了"); } }
配置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); //数字越小,启动优先级越高,但是必须大于0 return servletRegistrationBean; } }
但是不满足spring启动之后,spring不启动完成,就无法使用bean了,所以就按照前面的一种方法了
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
加载全部内容