SpringBoot 初始化资源
1 、使用接口ApplicationRunner和CommandLineRunner
这两个接口都是在容器运行后执行的,如下图示
如果项目需要在系统启动时,初始化资源,可以继承这两个接口,实现诸如缓存预热、DB连接等。
实现ApplicationRunner接口
@Component public class MyApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("缓存预热~"); System.out.println("DB连接~"); System.out.println("日志系统初始化~"); System.out.println("资源文件初始化~"); System.out.println("常驻后台线程的资源初始化~"); } }
实现CommandLineRunner接口
@Component public class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("缓存预热~"); System.out.println("DB连接~"); System.out.println("日志系统初始化~"); System.out.println("资源文件初始化~"); System.out.println("常驻后台线程的资源初始化~"); } }
2、监听spring事件ApplicationListener<>
ApplicationContext事件的实现机制是观察者模式,通过两个接口ApplicationEvent和ApplicationListener来实现。
spring容器在初始化时,会在不同的阶段,发布ApplicationEvent事件,因此,可以通过ApplicationListener监听各个阶段的事件来实现不同的功能。
spring提供了以下ApplicationEvent事件:
- ContextStartedEvent 上下文启动事件,此 Start 事件是当Spring容器启动时发布,即调用 start() 方法是执行,意味着所有Lifecyc Bean 都监听到了 start 事件。
- ContextRefreshedEvent 上下文刷新事件
此 Refreshed 事件是当容器实例化时发布,即执行 refresh() 方法,此时所有的 Bean 都已加载,后置处理器被激活,容器中所有的对象就可以使用,如果容器支持热重载,则 refresh 可以被触发多次(XmlWebApplicatonContext支持热刷新,而GenericApplicationContext则不支持)。
- ContextStoppedEvent 上下文停止事件 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
- ContextClosedEvent 上下文关闭事件 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
- RequestHandledEvent 请求处理完成事件 此 Request handled 事件只在使用spring的DispatcherServlet时有效,当一个请求被处理完成时发布。
基于以上事件类型,我们可以监听ContextRefreshedEvent事件,初始化系统资源,以及监听ContextStoppedEvent事件来清理资源。
初始化资源:
@Component public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("做一些初始化的工作,比如缓存预热~"); ApplicationContext ct= event.getApplicationContext(); System.out.println(ct); } }
清理资源:
@Component public class MyApplicationStopListener implements ApplicationListener<ContextStoppedEvent> { @Override public void onApplicationEvent(ContextStoppedEvent event) { System.out.println("做一些清理资源的工作,比如缓存清理,DB连接清理~"); ApplicationContext ct= event.getApplicationContext(); System.out.println(ct); } @Override public boolean supportsAsyncExecution() { return ApplicationListener.super.supportsAsyncExecution(); } }
3、@PostConstruct、@PreDestroy注解
@PostConstruct注解时针对Bean初始化完成后,要执行的方法,@PreDestroy注解时Bean销毁时执行。
@Component public class RedisInit { @PostConstruct public void init(){ System.out.println("缓存预热~"); } @PreDestroy public void destroy(){ System.out.println("缓存清理~"); } }
4、InitializingBean、DisposableBean接口
InitializingBean、DisposableBean 接口也是针对的Bean的。
@Component public class RedisInitializingBean implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("缓存预热~"); } @Override public void destroy() throws Exception { System.out.println("缓存清理~"); } }
5、配置Bean时,指定Bean的init和destroy方法
@Bean(name = "redisInit",initMethod = "init",destroyMethod = "") public RedisInit redisInit(){ return new RedisInit(); }