Spring Boot 中初始化资源的几种方式
假设有这么一个需求,要求在项目启动过程中,完成线程池的初始化,加密证书加载等功能,你会怎么做?如果没想好答案,请接着往下看。今天介绍几种在Spring Boot中进行资源初始化的方式,帮助大家解决和回答这个问题。
CommandLineRunner
- 定义初始化类
MyCommandLineRunner
- 实现
CommandLineRunner
接口,并实现它的run()
方法,在该方法中编写初始化逻辑 - 注册成Bean,添加
@Component
注解即可 - 示例代码如下:
package cn.zh.controller;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Componentpublic class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("项目初始化---------------11");
}
}
实现了 CommandLineRunner 接口的 Component 会在所有 Spring Beans 初始化完成之后, 在 SpringApplication.run() 执行之前完成。下面通过加两行打印来验证我们的测试。
package cn.zh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProcApplication {
public static void main(String[] args) {
System.out.println("...start SpringApplication.run");
SpringApplication.run(ProcApplication.class,args);
System.out.println("....end SpringApplication.run");
}
}
ApplicationRunner
- 定义初始化类
MyApplicationRunner
- 实现
ApplicationRunner
接口,并实现它的run()
方法,在该方法中编写初始化逻辑 - 注册成Bean,添加
@Component
注解即可 - 示例代码如下:
package cn.zh.controller;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("项目初始化二---------");
}
}
可以看到,通过实现 ApplicationRunner 接口,和通过实现 CommandLineRunner 接口都可以完成项目的初始化操作,实现相同的效果。两者之间唯一的区别是 run()
方法中自带的形参不相同,在 CommandLineRunner 中只是简单的String... args
形参,而 ApplicationRunner 则是包含了 ApplicationArguments 对象,可以帮助获得更丰富的项目信息。
@Order
如果项目中既有实现了 ApplicationRunner
接口的初始化类,又有实现了 CommandLineRunner
接口的初始化类,那么会是哪一个先执行呢?测试告诉我们,答案是实现了 ApplicationRunner
接口的初始化类先执行,我想这点倒是不需要大家过分去关注为什么。但如果需要改变两个初始化类之间的默认执行顺序,那么使用 @Order
注解就可以帮助我们解决这个问题。
@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
/**
* Callback used to run the bean.
*
* @param args incoming main method arguments
* @throws Exception on error
*/
@Override
public void run(String... args) throws Exception {
System.out.println("项目初始化---------------11");
}
}
@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("项目初始化二---------");
}
@PostConstruct
public void init(){
System.out.println("@PostConstruct初始化");
}
}
@PostConstruct
使用 @PostConstruct
注解同样可以帮助我们完成资源的初始化操作,前提是这些初始化操作不需要依赖于其它Spring beans的初始化工作。
可以看到 @PostConstruct
注解是用在方法上的,写一个方法测试一下吧。
@PostConstruct
public void init(){
System.out.println("@PostConstruct初始化");
}
注意:
- 只有一个非静态方法能使用此注解
- 被注解的方法不得有任何参数
- 被注解的方法返回值必须为void
- 被注解方法不得抛出已检查异常
- 此方法只会被执行一次
综上,使用
@PostConstruct
注解进行初始化操作的顺序是最快的,前提是这些操作不能依赖于其它Bean的初始化完成。通过添加@Order
注解,我们可以改变同层级之间不同Bean的加载顺序。
InitializingBean
InitializingBean 是 Spring 提供的一个接口,只包含一个方法 afterPropertiesSet()。凡是实现了该接口的类,当其对应的 Bean 交由 Spring 管理后,当其必要的属性全部设置完成后,Spring 会调用该 Bean 的 afterPropertiesSet()。
@Component
public class MyListener1 implements InitializingBean {
@Autowired
private ShopInfoMapper shopInfoMapper;
@Override
public void afterPropertiesSet() {
//使用spring容器中的bean
//System.out.println(shopInfoMapper.selectById("1").getShopName());
System.out.println("项目启动OK");
}
}
ApplicationListener
ApplicationListener 就是spring的监听器,能够用来监听事件,典型的观察者模式。如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。
其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。
同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。所以也能做到资源的初始化加载。
@Component
public class MyListener1 implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
//打印出每次事件的名称
System.out.println(applicationEvent.toString());
if (applicationEvent instanceof ApplicationReadyEvent) {
System.out.println("项目启动OK");
}
}
}
Spring Boot 中初始化资源的几种方式的更多相关文章
- Spring Boot 中初始化资源的几种方式(转)
假设有这么一个需求,要求在项目启动过程中,完成线程池的初始化,加密证书加载等功能,你会怎么做?如果没想好答案,请接着往下看.今天介绍几种在Spring Boot中进行资源初始化的方式,帮助大家解决和回 ...
- Spring Boot中初始化资源的几种方式
CommandLineRunner 定义初始化类 MyCommandLineRunner 实现 CommandLineRunner接口,并实现它的 run()方法,在该方法中编写初始化逻辑 注册成Be ...
- Spring Boot 中实现定时任务的两种方式
在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...
- spring boot中读取配置文件的两种方式
application.properties test.name=测试 test.url=www.test.com 1.@Value注解 在controller里可以这样直接调用 @Value(&qu ...
- Spring Boot定义系统启动任务的两种方式
Spring Boot定义系统启动任务的两种方式 概述 如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web ...
- Spring MVC中forward请求转发2种方式(带参数)
Spring MVC中forward请求转发2种方式(带参数) http://www.51gjie.com/javaweb/956.html
- JavaWeb应用中初始化Log4j的两种方式
本文主要介绍了普通JavaWeb应用(基于Tomcat)中初始化Log4j的两种方式: 1.通过增加 InitServlet ,设置令其自启动来初始化 Log4j . 2.通过监听器 ServletC ...
- Spring Boot中静态资源(JS, 图片)等应该放在什么位置
Spring Boot的静态资源,比如图片应该放在什么位置呢, 如果你放在传统WEB共的类似地方, 比如webapp或者WEB-INF下,你会得到一张示意文件未找到的破碎图片.那应该放哪里呢? 百度一 ...
- Spring3实战第二章第一小节 Spring bean的初始化和销毁三种方式及优先级
Spring bean的初始化和销毁有三种方式 通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法: 优先级第二通过 <bean& ...
随机推荐
- Docker磁盘空间分析与清理
首先使用du命令逐层分析docker磁盘的使用情况: (base) [root@openvino docker]# du -h --max-depth=1 | sort 0 ./containerd ...
- linux c 线程相关函数
线程相关函数(1)-pthread_create(), pthread_join(), pthread_exit(), pthread_cancel() 创建取消线程 一. pthread_creat ...
- 浅谈.net core如何使用EFCore为一个上下文注类型注入多个实例用于连接主从数据库
在很多一主多从数据库的场景下,很多开发同学为了复用DbContext往往采用创建一个包含所有DbSet<Model>父类通过继承派生出Write和ReadOnly类型来实现,其实可以通过命 ...
- python多版本切换
环境:Macbook MacOS自带的python2.7,在命令行中输入python后会显示2.7版本 如何切换成新版本? 一.修改用户配置环境变量~/.bash_profile 确定新版本的安装位置 ...
- C++职工管理系统
目录 职工管理系统 一. 需求 二. 创建管理类 1.创建文件 2. 头文件实现 3. 源文件实现 三. 菜单功能 1. 添加成员函数 2. 功能实现 3. 测试菜单功能 四. 退出功能 1. 提供功 ...
- ubuntu关机和重启
本博客旨在自我学习使用,如有任何疑问请及时联系博主 linux下常用的关机命令有:shutdown.halt.poweroff.init:重启命令有:reboot.下面本文就主要介绍一些常用的关机命令 ...
- 高可用 & 七层负载均衡与四层负载均衡
内容概要 高可用 七层负载均衡 和 四层负载均衡 内容详细 一.高可用 1.什么是高可用 一般是指2台机器启动着完全相同的业务系统,当有一台机器down机了,另外一台服务器就能快速的接管,对于访问的用 ...
- HashMap(1.7)源码学习
一. 1.7 和1.8区别 数据结构: 1.7: 数组 + 链表 1.8 : 数组 + 链表 + 红黑树 put: 1.7: 头插法 1.8: 尾插法 hash计算: 1.7 : Objects.ha ...
- 微服务从代码到k8s部署应有尽有系列(六、订单服务)
我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...
- close-on-exec 相关的一个 bug
close-on-exec 相关的一个 bug 测试一个用 V4L2 拍照的程序时,发现程序单独运行很正常,但在多进程环境下运行时就会出现问题,具体表现为执行 open 系统调用打开 /dev/vid ...