实践!在Spring Boot启动时添加方法运行,一文全懂!

2023-12-16

Springboot最佳实践:在Spring Boot启动时添加方法运行

在开发Spring Boot应用程序时,有时我们需要在启动时运行方法或一段代码。这段代码可以是任何内容,从记录某些信息到设置数据库,cron作业等。我们不能仅将此代码放入构造函数中,因为所需的变量或服务可能尚未初始化。这可能导致空指针或其他一些异常。

为什么我们需要在Spring Boot启动时运行代码?

由于多种原因,我们需要在应用程序启动时运行方法,

  • 记录重要的事情或说应用程序已启动的消息
  • 处理数据库或文件,建立索引,创建缓存等。
  • 启动后台进程,例如发送通知,从某些队列中获取数据等。

在Spring Boot中启动后运行方法的不同方法

每种方式都有其自身的优势。让我们详细看一下以确定应该使用哪个,

  1. 使用CommandLineRunner界面
  2. 带有ApplicationRunner界面
  3. Spring Boot应用程序事件
  4. @Postconstruct方法的注释
  5. InitializingBean接口
  6. @bean批注的Init属性

1.使用CommandLineRunner界面

CommandLineRunner是一个弹簧启动功能界面,用于在应用程序启动时运行代码。它位于软件包org.springframework.boot下。

在上下文初始化之后的启动过程中,spring boot使用提供给应用程序的命令行参数调用其run()方法。

要通知spring boot我们的commandlineRunner接口,我们可以实现它并在类上方添加@Component批注,或者使用@bean创建其bean。

实现CommandLineRunner接口的示例


  

java

复制代码

@Component public class CommandLineRunnerImpl implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("In CommandLineRunnerImpl "); for (String arg : args) { System.out.println(arg); } } }

创建CommandLineRunner接口Bean的示例


  

csharp

复制代码

@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } @Bean public CommandLineRunner CommandLineRunnerBean() { return (args) -> { System.out.println("In CommandLineRunnerImpl "); for (String arg : args) { System.out.println(arg); } }; } }

我们可以使用命令行或IDE运行应用程序。让我们举一个例子,当我们使用参数“ –status = running”运行应用程序时


  

arduino

复制代码

mvn spring-boot:run -Dspring-boot.run.arguments="--status=running"

要么


  

ini

复制代码

mvn package java -jar target/<FILENAME.JAR HERE> --status=running

这将产生以下日志输出:


  

ini

复制代码

In CommandLineRunnerImpl status=running

如我们所见,该参数未解析,而是解释为单个值“ status = running”。

要访问已解析格式的命令行参数,我们需要使用ApplicationRunner接口。我们待会儿再看。

Spring Boot将CommandLineRunner接口添加到启动过程中。因此,在commandliner Runner中引发异常将迫使Spring启动中止启动。

我们可以在一个应用程序中创建多个CommandLineRunner。使用Ordered接口或@Order批注,我们可以配置它们的运行顺序。较低的值表示较高的优先级。默认情况下,所有组件均以最低优先级创建。这就是为什么没有订单配置的组件将被最后调用的原因。

我们可以使用订单注释,如下所示


  

less

复制代码

@Component @Order(1) public class CommandLineRunnerImpl implements CommandLineRunner { ........ }

2.具有ApplicationRunner界面

如前所述,要访问已解析的参数,我们需要使用ApplicationRunner接口。ApplicationRunner接口为运行方法提供ApplicationArguments而不是原始字符串数组。

ApplicationArguments是一个接口,可从org.springframework.boot软件包下的boot 1.3 srping中获得。

它提供了以下几种访问参数的方法

String [] GetSourceArgs() 提供传递给应用程序的未处理参数
Set getOptionNames() 所有可选参数的名称,可选参数的前面都有**“ * -* “**如:-name =‘堆栈跟踪’
List getNonOptionArgs() 返回未处理的非可选参数。不带**“** *—* ”的 参数
布尔containsOption(字符串名称) 检查在可选参数中是否存在名称
List getOptionValues(字符串名称) 通过名称给出参数值

方法getOptionValues返回值列表,因为参数值可以是数组,因为我们可以在命令行中多次使用同一键。 例如**–name** =“ stacktrace” —端口= 8080 –name =“ guru”

作为接口实现的应用程序运行器示例

让我们使用“ status = running –mood = happy 10 –20”参数运行以下程序,并了解输出


  

kotlin

复制代码

@Component public class ApplicationRunnerImpl implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("ApplicationRunnerImpl Called"); //print all arguemnts: arg: status=running, arg: --mood=happy, 10, --20 for (String arg : args.getSourceArgs()) { System.out.println("arg: "+arg); } System.out.println("NonOptionArgs: "+args.getNonOptionArgs()); //[status=running,10] System.out.println("OptionNames: "+args.getOptionNames()); //[mood, 20] System.out.println("Printing key and value in loop:"); for (String key : args.getOptionNames()) { System.out.println("key: "+key); //key: mood //key: 20 System.out.println("val: "+args.getOptionValues(key)); //val:[happy] //val:[] } } }

输出:


  

vbnet

复制代码

ApplicationRunnerImpl Called arg: status=running arg: --mood=happ arg: 10 arg: --20 NonOptionArgs: [status=running , 10] OptionNames: [mood, 20] Printing key and value in loop: key: mood val: [happy] key: 20 val: []

CommandLineRunner和ApplicationRunner具有类似的功能,例如

  • run()方法中的异常将中止应用程序启动
  • 可以使用Ordered接口或@Order批注来订购多个ApplicationRunner

需要注意的最重要一点是,命令在CommandLineRunners和ApplicationRunners之间共享。这意味着可以在commandlinerRunner和applicationRunner之间混合执行顺序。

3. Spring Boot中的应用程序事件

Spring框架在不同情况下触发不同事件。它还会在启动过程中触发许多事件。我们可以使用这些事件来执行代码,例如,在Spring Boot应用程序启动后,可以使用ApplicationReadyEvent执行代码。

如果我们不需要命令行参数,这是在应用程序启动后执行代码的最佳方法。


  

csharp

复制代码

@Component public class RunAfterStartup{ @EventListener(ApplicationReadyEvent.class) public void runAfterStartup() { System.out.println("Yaaah, I am running........"); }

输出:


  

arduino

复制代码

Yaaah, I am running........

春季靴子中最重要的事件是

  • ApplicationContextInitializedEvent :在准备ApplicationContext并调用ApplicationContextInitializers之后但在加载bean定义之前触发
  • ApplicationPreparedEvent :在加载bean定义后触发
  • ApplicationStartedEvent :在刷新上下文之后但在调用命令行和应用程序运行程序之前触发
  • ApplicationReadyEvent :在调用任何应用程序和命令行运行程序之后触发
  • ApplicationFailedEvent :如果启动时发生异常则触发

可以创建多个ApplicationListeners。可以使用@Order批注或Ordered接口对其进行订购。

该顺序与其他相同类型的ApplicationListener共享,但不与ApplicationRunners或CommandLineRunners共享。

4.方法上的@Postconstruct注解

可以使用@PostConstruct批注标记方法。每当使用此注释标记方法时,将在依赖项注入后立即调用该方法。

@PostConstruct方法链接到特定的类,因此它仅应用于特定于类的代码。每个类只有一个带有postConstruct批注的方法。


  

csharp

复制代码

@Component public class PostContructImpl { public PostContructImpl() { System.out.println("PostContructImpl Constructor called"); } @PostConstruct public void runAfterObjectCreated() { System.out.println("PostContruct method called"); } }

输出:


  

sql

复制代码

PostContructImpl Constructor called postContruct method called

需要注意的是,如果class标记为lazy,则意味着在请求时创建了class。之后,将执行标有@postConstruct批注的方法。

标有postConstruct批注的方法可以具有任何名称,但是不能具有任何参数。它必须是无效的,并且不能是静态的。

请注意,@postConstruct批注是Java EE模块的一部分,在Java 9中被标记为已弃用,在Java 11中已被删除。我们仍然可以通过将java.se.ee添加到应用程序中来使用它。

5. InitializingBean接口

InitializingBean解决方案的工作原理与postConstruct批注完全相似。不必使用注释,我们必须实现InitializingBean接口。然后,我们需要重写afterPropertiesSet()方法。

InitializingBean是org.springframework.beans.factory包的一部分。


  

csharp

复制代码

@Component public class InitializingBeanImpl implements InitializingBean { public InitializingBeanImpl() { System.out.println("InitializingBeanImpl Constructor called"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBeanImpl afterPropertiesSet method called"); } }

您必须考虑如果同时使用@PostConstruct批注和InitializingBean会发生什么。那么在这种情况下,@PostConstruct方法将在InitializingBean的afterPropertiesSet()方法之前调用。

6. @bean批注的init属性

我们可以在@Bean批注中使用initMethod属性提供一种方法。bean初始化后将调用此方法。

initMethod中提供的方法必须为空,并且不能包含任何参数。此方法甚至可以是私有的。


  

typescript

复制代码

public class BeanInitMethodImpl { public void runAfterObjectCreated() { System.out.println("yooooooooo......... someone called me"); } } @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Bean(initMethod="runAfterObjectCreated") public BeanInitMethodImpl getFunnyBean() { return new BeanInitMethodImpl(); } }

输出:


  

sql

复制代码

yooooooooo......... someone called me

如果您具有同一类的InitializingBean实现和@Bean批注的initMethod属性,则将initMethod之前调用InitializingBean的afterPropertiesSet方法。

结合不同的方法:

最后,有时我们可能需要组合多个选项。然后,它们将按照以下顺序执行:

  • 建设者
  • 后构造方法
  • afterPropertiesSet方法
  • Bean初始化方法
  • ApplicationStartedEvent
  • ApplicationRunner或CommandLineRunner取决于顺序
  • ApplicationReadyEvent

快速阅读

  • 春季启动应用程序启动后,有多种方法可以运行代码
  • 我们可以使用CommandLineRunner或ApplicationRunner接口
  • 使用ApplicationRunner接口访问已解析的参数,而不是原始字符串数组
  • Spring Boot事件在应用程序启动时执行代码
  • 标有@PostConstruct批注的方法在对象初始化后执行
  • 对象初始化之后调用InitializingBean接口的afterPropertiesSet()方法
  • @Bean批注具有属性“ initMethod”以提供将在bean初始化后调用的方法

作者:小隐乐乐
链接:https://juejin.cn/post/6911568256289800206
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实践!在Spring Boot启动时添加方法运行,一文全懂! 的相关文章

随机推荐

  • GLAD:高斯光束的吸收和自聚焦效应

    概述 当一束强激光入射到介质中后 由于强光场与介质的非线性作用 使得介质的线性折射率上会叠加与入射光强相关的非线性折射率 当入射光束的光强呈现空间上的非均匀分布时 由此引入的非线性折射率也是非均匀的 这将使不同空间位置的光所经历的光程长度不
  • udp多播组播

    import socket struct time 组播地址和端口号 MCAST GRP 239 0 0 1 MCAST PORT 8888 创建UDP socket对象 sock socket socket socket AF INET
  • 应用反演工程对四层减反膜进行分析

    有很多的过程可以被称之为反演工程 但在Essential Macleod中 该术语的意思是用来识别理想设计的和实际生产尝试之间的差异 该功能大致可以概括为 出了什么问题 这一过程类似于优化 在优化过程中 将初始设计进行优化 以满足一组优化目
  • 《optisystem案例解析》好书分享

    目 录 安装OptiSystem 简介 快速入门 案例1 发射机 外调制激光 案例2 子系统 分层模拟 案例3 光学系统 WDM设计 案例4 参数扫描 BERx输入功率 案例5 双向模拟 使用多次迭代 案例6 时间驱动模拟 单独采样 案例7
  • CASAIM与广州大学达成冲击力分析检测合作,基于高精度3D测量技术探究不同厚度金属板材受力变形情况

    近期 CASAIM与广州大学达成冲击力分析检测合作 基于高精度3D测量技术探究不同厚度金属板材受力变形状态和受力分布 广州大学有着90多年的办学传统 紧紧抓住国家 双一流 建设 广东省和广州市高水平大学建设机遇 坚持 四个面向 深化与广州和
  • 杂散光好书分享《FRED操作手册上、下》

    目 录 第一章 FRED概述 1 1 1 WHAT IS FRED 1 1 2 FRED与传统软件之间有什么不同 1 1 3 FRED名词术语 2 1 4 FRED用户界面 7 第二章 光源 16 2 1 简易光源 16 2 1 1 简易光
  • 平面电磁波散射中麦克斯韦方程组的米氏解

    摘要 平面波对于任意半径和折射率的球形粒子的吸收和散射问题 米氏解是严格的麦克斯韦求解器 其得到的散射效应十分依赖于粒子的大小 根据其特性 散射可以分为瑞利散射 米氏散射和几何光学散射 VirtualLab Fusion中包含了完整的米氏解
  • 杂散光好书分享《FRED操作手册上、下》

    目 录 第一章 FRED概述 1 1 1 WHAT IS FRED 1 1 2 FRED与传统软件之间有什么不同 1 1 3 FRED名词术语 2 1 4 FRED用户界面 7 第二章 光源 16 2 1 简易光源 16 2 1 1 简易光
  • 二维周期光栅结构的配置

    摘要 复杂光学光栅结构被广泛用于多种应用 如光谱仪 近眼显示系统等 利用傅里叶模态法 FMM 或称RCWA VirtualLab Fusion 提供了一种用于任意光栅结构严格分析的简单方法 利用图形用户界面 用户可以设置堆栈的几何形状 从而
  • 《VirtualLab Fusion物理光学实验教程》好书分享

    目录 第一章 物理光学概念介绍 6 1 1 几何光学和光线追迹 6 1 2 物理光学和光场追迹 6 1 3 电场 磁场以及坡印廷矢量 8 1 4 振幅 相位及实部和虚部 9 1 5 振幅 相位与偏振 10 1 6菲涅尔公式 11 1 7 全
  • ADB:常用指令汇总

    常用指令
  • 用与球形粒子散射的MIE解

    光的散射是最基本的光效应之一 对于大小与光的波长相当的散射粒子 例如空气中的液滴或气态污染物 需要进行精确的处理才能建立足够精确的模型 米氏解 也称为洛伦兹 米氏解 或米氏散射 已在VirtualLab Fusion中用于研究球形粒子的散射
  • Python:用python脚本,自动翻阅Andriod手机小说

    一 需求描述 在 Windows10 环境下 通过 Python 脚本 实现自动翻阅 Andriod 手机上的小说 二 安装adb 下载地址 ADB官网 下载后 直接解压即可 然后 配置 adb 的环境变量 查看 adb 版本 adb ve
  • Markdown编辑器使用笔记

    这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题 有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适
  • 字节内网被催更的漫画:实习四个月,我的真实体验!

    小米前端日常实习 拼多多 非必要就别去了吧 一个985废物的春招诈骗史 秋招总结 逃离互联网哩 苹果公司嵌入式工程师面经 offer选择 拒了华为 重回0 offer 解约的同学看过来 提供一份解约思路 每人进来骂一句 我就能改简历改到死
  • 开发者都能玩转的大模型训练

    本篇文章授权活动官方亚马逊云科技文章转发 改写权 包括不限于在 亚马逊云科技开发者社区 知乎 自媒体平台 第三方开发者媒体等亚马逊云科技官方渠道 目录 前言 概念基础 原理核心 入手体验 体验收获 结束语 参考文献 前言 看了刚结束的亚马逊
  • GitHub Universe 2023 Watch Party in Shanghai:开源开发者日盛会

    目录 前言 GitHub Universe 2023的背景 开源开发者日活动亮点 本次参会的意义 活动日程 最后 前言 作为全球最大的代码托管平台 GitHub每年都会举办一场令开源开发者们翘首以待的盛会 GitHub Universe 今
  • Vue:监视属性功能实现

    一 普通监视 基础案例代码片段 这里 主要是监视 isHot 变量的变化 const vm new Vue el root data isHot true computed info return this isHot 炎热 凉爽 meth
  • 电磁场与纳米圆柱体的相互作用

    摘要 电磁场和光的波长尺度的纳米结构的相互作用必须使用严格的Maxwell求解器进行研究 通过将完美匹配层 PML 技术与傅立叶模态方法 FMM 相结合 可以在VirtualLab Fusion中对非周期性纳米结构进行建模 本示例研究了聚焦
  • 实践!在Spring Boot启动时添加方法运行,一文全懂!

    Springboot最佳实践 在Spring Boot启动时添加方法运行 在开发Spring Boot应用程序时 有时我们需要在启动时运行方法或一段代码 这段代码可以是任何内容 从记录某些信息到设置数据库 cron作业等 我们不能仅将此代码