SpringBoot中资源初始化加载的几种方式(看这一片就够了)
原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/11117665.html,谢谢支持哈!!!
一、问题
在平时的业务模块开发过程中,难免会需要做一些全局的任务、缓存、线程等等的初始化工作,那么如何解决这个问题呢?方法有多种,但具体又要怎么选择呢?
二、资源初始化
1、既然要做资源的初始化,那么就需要了解一下springboot启动过程(这里大体说下启动过程,详细:https://www.cnblogs.com/dennyzhangdd/p/8028950.html)

按照前面的分析,Spring-boot容器启动流程总体可划分为2部分:
- 执行注解:扫描指定范围下的bean、载入自动配置类对应的bean加载到IOC容器。
- man方法中具体SpringAppliocation.run(),全流程贯穿SpringApplicationEvent(经典的spring事件驱动模型),有6个子类:
- ApplicationFailedEvent.class
- ApplicationPreparedEvent.class
- ApplicationReadyEvent.class
- ApplicationStartedEvent.class
- ApplicationStartingEvent.class
- SpringApplicationEvent.class
2、CommandLineRunner和ApplicationRunner
由上可知,我们只要实现这两个中的任何一个接口便可以完成我们的资源初始化任务,可以看到它们的加载是在容器完全启动之前。它两的区别是:前者的run方法参数是String...args,直接传入字符串,后者的参数是ApplicationArguments,对参数进行了封装。功能上是一样的。同时也可以使用 @Order注解来实现资源加载的先后顺序,值越小,优先级越高。实例如下:
@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("...init resources by implements CommandLineRunner");
}
}
@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
System.out.println("...init resources by implements ApplicationRunner");
}
}
3、@PostConstruct
在具体Bean的实例化过程中执行,@PostConstruct注解的方法,会在构造方法之后执行,顺序为Constructor > @Autowired > @PostConstruct > 静态方法,所以这个注解就避免了一些需要在构造方法里使用依赖组件的尴尬(与之对应的还有@PreDestroy,在对象消亡之前执行,原理差不多)。使用特点如下:
只有一个非静态方法能使用此注解
被注解的方法不得有任何参数
被注解的方法返回值必须为void
被注解方法不得抛出已检查异常
此方法只会被执行一次
@Component
public Class AAA {
@Autowired
private BBB b; public AAA() {
System.out.println("此时b还未被注入: b = " + b);
}
@PostConstruct
private void init() {
System.out.println("此时b已经被注入: b = " + b);
}
}
4、InitializingBean
InitializingBean 是 Spring 提供的一个接口,只包含一个方法 afterPropertiesSet()。凡是实现了该接口的类,当其对应的 Bean 交由 Spring 管理后,当其必要的属性全部设置完成后,Spring 会调用该 Bean 的 afterPropertiesSet()。在Bean在实例化的过程中执执行顺序为:Constructor > @PostConstruct > InitializingBean > init-method
public class InitSequenceBean implements InitializingBean {
public InitSequenceBean() {
System.out.println("InitSequenceBean: constructor");
}
@PostConstruct
public void postConstruct() {
System.out.println("InitSequenceBean: postConstruct");
}
public void initMethod() {
System.out.println("InitSequenceBean: init-method");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitSequenceBean: afterPropertiesSet");
}
}
5、ApplicationListener
ApplicationListener 就是spring的监听器,能够用来监听事件,典型的观察者模式。如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。所以也能做到资源的初始化加载!
@Component
public class DataSourceInitListener implements ApplicationListener<ContextRefreshedEvent> {//ContextRefreshedEvent为启动事件
private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceInitListener.class);
@Autowired
private SystemConfigService systemConfigService;
@Autowired
private ItemService itemService;
@Autowired
private SystemResultService systemResultService;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(event.getApplicationContext().getParent() == null) {//判断是否执行过,执行过则不再执行
LOGGER.info("初始化systemConfig数据");
systemConfigService.initConfig();
LOGGER.info("初始化返回消息数据");
systemResultService.initResult();
LOGGER.info("系统初始化结束...........");
}
}
}
三、总结
- 到此一些资源初始化的方法就说的差不多了,其中不免有些错误的地方,或者理解有偏颇的地方欢迎大家提出来!
个人博客地址:
segmentfault:https://segmentfault.com/u/baixianlong
SpringBoot中资源初始化加载的几种方式(看这一片就够了)的更多相关文章
- SpringBoot中资源初始化加载的几种方式
一.问题 在平时的业务模块开发过程中,难免会需要做一些全局的任务.缓存.线程等等的初始化工作,那么如何解决这个问题呢?方法有多种,但具体又要怎么选择呢? 二.资源初始化 1.既然要做资源的初始化,那么 ...
- Unity中资源动态加载的几种方式比较
http://blog.csdn.net/leonwei/article/details/18406103 初学Unity的过程中,会发现打包发布程序后,unity会自动将场景需要引用到的资源打包到安 ...
- 如果你还不知道如何控制springboot中bean的加载顺序,那你一定要看此篇
1.为什么需要控制加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了spi机制,用spring.factories可以完成一个小组件的自动装配功 ...
- 点评js异步加载的4种方式
主要介绍了点评js异步加载的4种方式,帮助大家更全面的了解js异步加载方式,感兴趣的小伙伴们可以参考一下 js异步加载的4种方式,点评开始. <!DOCTYPE html> <htm ...
- route按需加载的3种方式:vue异步组件、es提案的import()、webpack的require.ensure()
1. vue异步组件技术 vue-router配置路由,使用vue的异步组件技术,可以实现按需加载. 但是,这种情况下一个组件生成一个js文件.举例如下: { path: '/promisedemo' ...
- HBase协处理器加载的三种方式
本文主要给大家罗列了HBase协处理器加载的三种方式:Shell加载(动态).Api加载(动态).配置文件加载(静态).其中静态加载方式需要重启HBase. 我们假设我们已经有一个现成的需要加载的协处 ...
- Spring中资源的加载原来是这么一回事啊!
1. 简介 在JDK中 java.net.URL 适用于加载资源的类,但是 URL 的实现类都是访问网络资源的,并没有可以从类路径或者相对路径获取文件及 ServletContext , 虽然可以通过 ...
- APP中数据加载的6种方式-b
我们看到的APP,往往有着华丽的启动界面,然后就是漫长的数据加载等待,甚至在无网络的时候,整个处于不可用状态.那么我们怎么处理好界面交互中的加载设计,保证体验无缝衔接,保证用户没有漫长的等待感,而可以 ...
- Flask程序相关配置加载的三种方式
方式一:从对象中加载配置 1.定义配置类,在配置类中添加相应的配置 2.通过app.config.from_object(配置类)进行加载 代码如下: from flask import Flask ...
随机推荐
- JS 实现Map
function Map() { this.arr = new Array(); var struct = function(key, value) { this.key = key; this.va ...
- WPF 设置控件阴影后,引发的Y轴位置变化问题
原文:WPF 设置控件阴影后,引发的Y轴位置变化问题 背景 最近遇到一个动画执行时,文本位置变化的问题.如下图: 如果你仔细看的话,当星星变小时,文本往下降了几个像素. 貌似有点莫名其妙,因为控件之间 ...
- C#中将字符串转换成Md5值的方法
原文:C#中将字符串转换成Md5值的方法 版权声明:有问题可联系博主QQ:15577969,大家一起相互交流和学习. https://blog.csdn.net/qq15577969/article/ ...
- PostSharp-4.3.33安装包_KeyGen发布
PostSharp-4.3.33安装包_KeyGen发布 请低调使用. PostSharp安装及注册步骤截图.rar 请把浏览器主页设置为以下地址支持本人.https://www.duba.com/? ...
- C++ Boost 学习资源列表
文档书籍下载 Boost Documentation Boost代码下载 优秀网站导航 Boost官方网站 Boost中文站 Boost Consulting 专题资源报告 Lin ...
- C#代码中设置 控件的触发器
Style style = new Style(); style.TargetType = typeof(TextBox); MultiDataTrigger trigger = new MultiD ...
- 图像滤镜艺术--编码基础(Photoshop基础变换的代码实现)
原文:图像滤镜艺术--编码基础(Photoshop基础变换的代码实现) 自从上一篇博客写完之后,到现在已经有段时间了,这段时间不是不想接着写,只是想做的更好了在写出来给大家看呵呵. 今天,我将给大家介 ...
- Android 命令设置获取、IP地址、网关、dns
设置ip root@android:/ # ifconfig eth0 192.168.0.173 netmask 255.255.255.0 ifconfig eth0 192.168.0.173 ...
- win10 uwp 如何打包Nuget给其他人
原文:win10 uwp 如何打包Nuget给其他人 本文告诉大家,如果自己有做一些好用的库,如何使用 Nuget 打包之后上传,分享给大家. 首先需要知道一些 Nuget 打包需要知道的,请看 wi ...
- Android多线程(三)
上次讲了关于Android多线程中通信中Thread.Handler.Looper等的基础概念和基本用法,用现实世界两个人写信交流的过程来理解是再好不过了.但是不得不说这一套完整的细节的确很繁琐,好在 ...