Spring Boot启动时执行初始化操作的几种方式
场景
项目中,经常需要在启动过程中初始化一些数据,如从数据库读取一些配置初始化,或从数据库读取一些热点数据到redis进行初始化缓存。
方式一:实现CommandLineRunner 接口重写run方法逻辑
CommandLineRunner是Spring提供的接口,定义了一个run()方法,用于执行初始化操作。
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
public class InitConfigCommand implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("CommandLineRunner:"+"{}"+"接口实现方式重写");}
}
CommandLineRunner的执行时机为Spring beans初始化之后,因此CommandLineRunner的执行一定是晚于@PostConstruct的。
若有多组初始化操作,则每一组操作都要定义一个CommandLineRunner派生类并实现run()方法。这些操作的执行顺序使用@Order(n)来设置,n为int型数据。
@Component
@Order(99)
public class CommandLineRunnerA implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("初始化:CommandLineRunnerA");}
}@Component
@Order(1)
public class CommandLineRunnerB implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("初始化:CommandLineRunnerB");}
}
如上,会先执行CommandLineRunnerB的run(),再执行CommandLineRunnerA的run()。
@Order(n)中的n较小的会先执行,较大的后执行。n只要是int值即可,无需顺序递增。
方式二:实现ApplicationRunner接口重写run方法逻辑
ApplicationRunner接口与CommandLineRunner接口类似,都需要实现run()方法。二者的区别在于run()方法的参数不同:
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;@Component
public class InitConfig implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {System.out.println("项目启动初始化");}
}
ApplicationRunner接口的run()参数为ApplicationArguments对象,因此可以获取更多项目相关的内容。
ApplicationRunner接口与CommandLineRunner接口的调用时机也是相同的,都是Spring beans初始化之后。因此ApplicationRunner接口也使用@Order(n)来设置执行顺序。
方式三:使用@PostConstruct注解的方式
对于注入到Spring容器中的类,在其成员函数前添加@PostConstruct注解,则在执行Spring beans初始化时,就会执行该函数。
但由于该函数执行时,其他Spring beans可能并未初始化完成,因此在该函数中执行的初始化操作应当不依赖于其他Spring beans。
@Component
public class Construct {@PostConstructpublic void doConstruct() throws Exception {System.out.println("初始化:PostConstruct");}
}
初始化顺序
- @PostConstruct 注解方法
- CommandLineRunner接口实现
- ApplicationRunner接口实现
扩展
@PostConstruct注解使用在方法上,它可以被用来标注一个非静态的 void 方法,这个方法会在该类被 Spring 容器初始化后立即执行。因为它的执行时机是在依赖注入之后,对象构造完成之后,也就是说是在@Autowired注入之后执行。所以这里可以进行一些初始化操作,如某些需要在对象创建后才能进行的数据初始化操作。
需要注意以下几点:
- @PostConstruct 只能用在方法上面,而不能用在属性或构造函数上。
- 一个类中可以有多个使用 @PostConstruct 注解的方法,但执行顺序并不是固定的。
- @PostConstruct 注解的方法在本类中必须是无参数的,如果有参数,那么这个方法不会被执行。
- @PostConstruct 注解的方法在实现上可以使用任意修饰符。
假设我们有一个需要初始化数据的类:
public class InitService {private List<String> data;public InitService() {this.data = Arrays.asList("A", "B", "C");}@PostConstructpublic void init() {data.add("D");}public List<String> getData() {return this.data;}
}
当我们实例化 InitService 时,构造函数会为 data 属性赋初值,而 @PostConstruct 注解的 init 方法会在 Spring 容器实例化完 InitService 后被执行,将 “D” 添加到 data 列表中。所以当我们调用 getData() 方法时,返回的列表应该是 [A, B, C, D]。
接下来看看 @Autowired 和@PostConstruct 的具体执行顺序
@Service
public class TestA {static {System.out.println("staticA");}@Autowiredprivate TestB testB;public TestA() {System.out.println("这是TestA 的构造方法");}@PostConstructprivate void init() {System.out.println("这是TestA的 init 方法");testB.test();}
}
@Service
public class TestB {static {System.out.println("staticB");}@PostConstructprivate void init() {System.out.println("这是TestB的init 方法");}public TestB() {System.out.println("这是TestB的构造方法");}void test() {System.out.println("这是TestB的test方法");}
}
构造方法:在对象初始化时执行。执行顺序在static静态代码块之后。
服务启动后,输出结果如下:
staticA
这是TestA 的构造方法
staticB
这是TestB的构造方法
这是TestB的init 方法
这是TestA的 init 方法
这是TestB的test方法
结论为:等@Autowired注入后,在执行@PostConstruct注解的方法。
方式四:静态代码块
static静态代码块,在类加载的时候即自动执行。
使用的static静态代码块,实现原理为@Component + static代码块, spring boot项目在启动过程中,会扫描@Component 并初始化相应的类,类的初始化过程会运行静态代码块。
@Component
public class WordInitConfig {static {WordSegmenter.segWithStopWords("初始化分词");}
}
所以得到结论
static>constructer>@Autowired>@PostConstruct>ApplicationRunner>CommandLineRunner
相关文章:
Spring Boot启动时执行初始化操作的几种方式
场景 项目中,经常需要在启动过程中初始化一些数据,如从数据库读取一些配置初始化,或从数据库读取一些热点数据到redis进行初始化缓存。 方式一:实现CommandLineRunner 接口重写run方法逻辑 CommandLineRunner是Spring提供的接口࿰…...
考研失败, 学点Java打小工——Day3
1 编码规范——卫语句 表达异常分支时,少用if-else方式。 比如成绩判断中对于非法输入的处理: /*>90 <100 优秀>80 <90 良好>70 <80 一般>60 <70 及格<60 不及格*/Testpu…...
【Stable Diffusion】入门-01:原理简介+应用安装(Windows)+生成步骤
【Stable Diffusion】入门:原理简介应用安装(Windows)生成步骤 原理简介应用安装 原理简介 稳定扩散生成模型(Stable Diffusion)是一种潜在的文本到图像扩散模型,能够在给定任何文本输入的情况下生成照片般逼真的图像。 应用安…...
VueX详解
Vuex 主要应用于Vue.js中管理数据状态的一个库通过创建一个集中的数据存储,供程序中所有组件访问 使用场景 涉及到非父子关系的组件,例如兄弟关系、祖孙关系,甚至更远的关系组件之间的联系中大型单页应用,考虑如何更好地在组件外部…...
2023 年 9 月青少年软编等考 C 语言一级真题解析
目录 T1. 日期输出思路分析 T2. 计算 (a b) (c - b) 的值思路分析 T3. 有一门课不及格的学生思路分析 T4. 特殊求和T5. 比 n 小的最大质数 T1. 日期输出 给定两个整数,表示一个日期的月和日。请按照 "MM-DD" 的格式输出日期,即如果月和日不…...
避免阻塞主线程 —— Web Worker 示例项目
前期回顾 迄今为止易用 —— 的 “盲水印“ 实现方案-CSDN博客https://blog.csdn.net/m0_57904695/article/details/136720192?spm1001.2014.3001.5501 目录 CSDN 彩色之外 📝 前言 🚩 技术栈 🛠️ 功能 🤖 如何运行 ♻️ …...
matlab 基操~
MATLAB基本操作 1. 对象定义 使用sym定义单个对象、使用syms定义多个对象 2. 使用limit求极限 $$ \lim_{v \rightarrow a} f(x) $$ limit(f,v,a) % 使用limit(f,v,a,left)可求左极限 3. 导数 使用diff(f,v,n)对$ f(v)v^{t-1} $求 $ n $ 阶导 $ \frac{d^nf}{d^nv} $…...
HTML5、CSS3面试题(一)
1、H5 的新特性有哪些?C3 的新特性有哪些?(必会) H5 新特性 1、拖拽释放(Drap and drop) API ondrop 拖放是一种常见的特性,即抓取对象以后拖到另一个位置 在 HTML5 中,拖放是标准的一部分,任…...
图片压缩神器源码系统:无损画质 带完整的代码安装包以及搭建教程
在数字化时代,图片已经成为我们日常生活和工作中不可或缺的一部分。然而,随着图片数量的增加和质量的提升,存储空间的问题也日益凸显。如何在保证图片质量的前提下,有效减少图片的大小,成为了一个亟待解决的问题。罗峰…...
探索SOCKS5代理、代理IP、HTTP与网络安全
在这个数字化时代,网络安全已成为我们日常生活中不可或缺的一部分。作为一名软件工程师,深入理解网络通信的核心技术,如SOCKS5代理、代理IP、HTTP协议,以及它们在网络安全中的应用,对于设计和实施安全的网络应用至关重…...
【Python学习篇】Python基础入门学习——你好Python(一)
个人名片: 🦁作者简介:学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755qq.com 🦉个人WeChat:Vir2021GKBS 🐼本文由…...
【通信原理笔记】【二】随机信号分析——2.2 平稳随机过程
文章目录 前言一、平稳随机过程1.1 广义平稳过程1.2 遍历性 二、两个随机过程之间的关系2.1 联合平稳2.2 随机过程的相关关系2.2.1 随机变量的不相关2.2.2 随机过程的不相关 总结 前言 我们学习了随机信号以及随机信号的相关函数与功率谱的计算方法,但是这种计算还…...
新火种AI|GPT-4诞生1年,OpenAI把它放到了机器人上
作者:一号 编辑:美美 ChatGPT拥有了身体,机器人也有了灵魂。 从OpenAI在去年3月14日拿出GPT-4后,已经过了整整一年。显然,在GPT-4诞生之后的这一年,一切都迭代得太快了,从GPT-4展现多模态能力&…...
8-图像放大
其实,就是开辟一个zoomwidth,zoomheight的内存,再分别赋值即可。 void CDib::Maginify(float xZoom, float yZoom) { //指向原图像指针 LPBYTE p_data GetData(); //指向原像素的指针 LPBYTE lpSrc; //指向缩放图像对应像素的指针 LPBYTE l…...
java实现压缩文件夹(层级压缩)下载,java打包压缩文件夹下载
工具类如下 打包下载方法:exportZip(支持整个文件夹或单文件一起) 注意:前端发送请求不能用ajax,form表单提交可以,location.href也可以,window.open也可以,总之就ajax请求就是不行 import com.…...
Visual Studio 2022 配置“Debug|x64”的 Designtime 生成失败。IntelliSense 可能不可用。
今天写代码,无缘无故就给我整个这个错误出来,我一头雾水。 经过我几个小时的奋战,终于解决问题 原因就是这个Q_INTERFACES()宏,我本想使用Q_DECLARE_INTERFACE Q_INTERFACES这两个Qt宏实现不继承QObject也能使用qobjec…...
Pandas教程16:DataFrame列标题批量重命名+空df数据判断+列名顺序重排
---------------pandas数据分析集合--------------- Python教程71:学习Pandas中一维数组Series Python教程74:Pandas中DataFrame数据创建方法及缺失值与重复值处理 Pandas数据化分析,DataFrame行列索引数据的选取,增加,…...
React.FC介绍
React.FC是React中的一种函数组件类型,是在TypeScript中使用的一个泛型,FC即Function Component的缩写,表示一个接收props作为输入并返回JSX元素的函数组件。 使用React.FC可以为组件定义类型,提供props的类型作为泛型参数&#x…...
为什么要用scrapy爬虫库?而不是纯python进行爬虫?
为什么要用scrapy爬虫库?而不是纯python进行爬虫? Scrapy的优点Scrapy节省的工作使用纯Python编写爬虫的不足 Scrapy是一个使用Python编写的开源和协作的web爬虫框架,它被设计用于爬取网页数据并从中提取结构化数据。Scrapy的强大之处在于其广…...
C:数据结构王道
初始化顺序表(顺序表中元素为整型),里边的元素是1,2,3,然后通过scanf读取一个元素(假如插入的是6),插入到第2个位置,打印输出顺序表,每个元素占3个空格,格式为…...
高效获取B站视频到本地存储:BilibiliDown工具全攻略
高效获取B站视频到本地存储:BilibiliDown工具全攻略 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/…...
Emmc系列(二)--------协议解析与实战应用
1. Emmc协议基础解析 Emmc协议作为嵌入式存储领域的核心标准,其重要性不言而喻。简单来说,它就像存储设备与主机之间的"普通话",规定了双方如何高效沟通。我在实际项目中遇到过不少因为协议理解不到位导致的通信故障,今…...
Alpamayo-R1-10B参数详解:Top-p=0.98与Temperature=0.6组合的工程意义解析
Alpamayo-R1-10B参数详解:Top-p0.98与Temperature0.6组合的工程意义解析 1. 项目背景与技术架构 1.1 Alpamayo-R1-10B核心定位 Alpamayo-R1-10B是NVIDIA开发的自动驾驶专用视觉-语言-动作(VLA)模型,其核心设计目标是通过类人因果推理能力提升自动驾驶…...
为什么LivePortrait能吊打Diffusion模型?揭秘快手69M训练数据背后的技术取舍
LivePortrait为何能突破扩散模型瓶颈?解析69M训练数据驱动的工业级优化策略 当开源社区还在为扩散模型的生成质量惊叹时,快手LivePortrait团队已经用12.8ms/帧的推理速度和6.5K GitHub星标证明:在工业级人像动画领域,隐式关键点框…...
英雄联盟智能助手:如何在选人阶段获得不公平优势?终极指南揭秘本地化工具LeagueAkari
英雄联盟智能助手:如何在选人阶段获得不公平优势?终极指南揭秘本地化工具LeagueAkari 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League…...
如何快速批量下载知网文献?CNKI-download自动化工具终极指南
如何快速批量下载知网文献?CNKI-download自动化工具终极指南 【免费下载链接】CNKI-download :frog: 知网(CNKI)文献下载及文献速览爬虫 项目地址: https://gitcode.com/gh_mirrors/cn/CNKI-download 对于学术研究者和学生来说,从知网࿰…...
李慕婉-仙逆-造相Z-Turbo AI核心原理科普:如何用Transformer理解并生成人类语言
李慕婉-仙逆-造相Z-Turbo AI核心原理科普:如何用Transformer理解并生成人类语言 你有没有想过,当你和“李慕婉-仙逆-造相Z-Turbo”这样的AI模型对话时,它到底是怎么“听懂”你的话,又“想”出那些回答的?它不像我们人…...
【数据结构】数组与特殊矩阵
数据结构的学习中,数组与特殊矩阵是基础且核心的内容。它们不仅是程序设计中最常用的线性结构,更是处理复杂矩阵运算的基础。本文将结合解析与真题,带你彻底搞懂数组的存储方式和特殊矩阵的压缩存储技巧。一、一维数组与二维数组:…...
CasRel在智能问答系统中的落地实践:为QA引擎注入结构化事实支撑
CasRel在智能问答系统中的落地实践:为QA引擎注入结构化事实支撑 1. 引言:当问答系统遇到关系抽取 想象一下这样的场景:用户向智能问答系统提问"苹果公司的CEO是谁?",系统需要快速准确地回答"蒂姆库克…...
OpenClaw人人养虾:配置Anthropic (Claude)
Anthropic 是 Claude 系列模型的开发者。Claude 以出色的指令遵循能力、深度推理和长文本处理著称。OpenClaw 支持通过 API Key 或 Claude Code CLI OAuth 接入。 认证方式 方式一:API Key(推荐) 前往 Anthropic Console 创建 API Key在 O…...
