SpringBoot2.x入门:使用CommandLineRunner钩子接口

简介: 这篇文章是《SpringBoot2.x入门》专辑的「第6篇」文章,使用的SpringBoot版本为2.3.1.RELEASE,JDK版本为1.8。这篇文章主要简单聊聊钩子接口CommandLineRunner和ApplicationRunner,下文有时候统称两者为Runner。

微信截图_20220513123019.png


前提



这篇文章是《SpringBoot2.x入门》专辑的第6篇文章,使用的SpringBoot版本为2.3.1.RELEASEJDK版本为1.8


这篇文章主要简单聊聊钩子接口CommandLineRunnerApplicationRunner,下文有时候统称两者为Runner


Runner的回调时机



参考org.springframework.boot.SpringApplication#run()方法的源码,可以知道CommandLineRunnerApplicationRunner的回调时机:


微信截图_20220513123028.png


在所有的CommandLineRunnerApplicationRunner回调之前,下面的步骤已经确保执行完毕:


  1. Environment内置变量的创建和属性填充已经完成。
  2. Banner已经打印完毕。
  3. ApplicationContextBeanFactory创建完成,并且完成了上下文刷新(refreshContext),意味着所有单例的Bean完成了初始化以及属性装配。
  4. Servlet容器启动成功,如内置的TomcatJetty容器已经正常启动,可以正常接收请求和处理。
  5. 启动信息完成打印,一般会看到日志输出类似Started OrderExportApplication in XXX seconds (JVM running for YYY)

也就是CommandLineRunner或者ApplicationRunner回调的时候,可以使用所有上下文中存在的单例BeanEnvironment内置变量中已经存在的属性值,所以很多时候demo项目都会在CommandLineRunner或者ApplicationRunner中进行操作。


Runner的简单使用



CommandLineRunnerApplicationRunner没有本质区别,唯一的区别在:CommandLineRunner#run()接收来自于main方法的参数,类型是字符串数组(不定字符串数组),而ApplicationRunner#run()接收ApplicationArguments类型的参数,对应的实现类是DefaultApplicationArguments


可以直接把注解@Component应用在CommandLineRunner或者ApplicationRunner的实现类上,相对于把对应的实现单例添加到Spring上下文中。例如:


@Slf4j
@Component
public class CustomCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info("CustomCommandLineRunner runs...");
    }
}
复制代码


也可以通过@Bean注解,直接作用于CommandLineRunner的匿名类对应的方法上,例如:


@Slf4j
@Configuration
public class CommandLineRunners {
    @Bean
    public CommandLineRunner commandLineRunner(){
        return args -> log.info("CommandLineRunners commandLineRunner");
    }
}
复制代码


或者直接在启动类实现CommandLineRunner接口(这种方式不推荐使用):


@Slf4j
@SpringBootApplication
public class Ch5Application implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(Ch5Application.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        log.info("Ch5Application CommandLineRunner runs...");
    }
}
复制代码


此外,可以通过实现org.springframework.core.Ordered接口或者@Order注解定义Runner回调的顺序,指定的顺序数越小,优先级越高。


Runner的使用场景



这一小节是根据个人的编程习惯提出的建议。Runner钩子接口回调的时候如果抛出异常,会直接导致应用进程退出,所以如果在Runner回调方法中一定要注意异常的捕获和处理。基于这个特性,结合前面分析Runner接口的回调时机,它适用的主要场景有:


  • 打印日志用于标识服务启动成功或者标识某些属性加载成功。
  • 设置属性值或者启动组件,例如开启某些组件的开关、一些应用级别缓存的加载、启动定时任务等等。
  • 预加载数据(更常见于一些测试场景中,可以结合@Profile注解使用,指定特定的profile才生效)。
  • 需要使用main方法的入参。


下面使用CommandLineRunner启动所有Quartz中的Job(记得先引入依赖spring-boot-starter-quartz以及quartz),为了简单起见调度器使用内存态:


@Slf4j
@DisallowConcurrentExecution
public class SimpleJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        log.info("SimpleJob run...");
    }
}
@Component
public class QuartzCommandLineRunner implements CommandLineRunner {
    @Autowired
    private Scheduler scheduler;
    @Override
    public void run(String... args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class).storeDurably().withIdentity(JobKey.jobKey("SimpleJob")).build();
        // 30秒执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatForever().withIntervalInSeconds(30))
                .forJob(job).build();
        scheduler.scheduleJob(job, trigger);
    }
}
复制代码


启动应用后,日志如下:


微信截图_20220513123038.png


小结



本文demo项目仓库:



(本文完 c-2-d e-a-20200712 封面图来自于《可塑性记忆》)

相关文章
|
18天前
|
Java 开发者 Spring
精通SpringBoot:16个扩展接口精讲
【10月更文挑战第16天】 SpringBoot以其简化的配置和强大的扩展性,成为了Java开发者的首选框架之一。SpringBoot提供了一系列的扩展接口,使得开发者能够灵活地定制和扩展应用的行为。掌握这些扩展接口,能够帮助我们写出更加优雅和高效的代码。本文将详细介绍16个SpringBoot的扩展接口,并探讨它们在实际开发中的应用。
36 1
|
24天前
|
存储 安全 Java
|
24天前
|
存储 算法 安全
SpringBoot 接口加密解密实现
【10月更文挑战第18天】
|
22天前
|
监控 Java 开发者
掌握SpringBoot扩展接口:提升代码优雅度的16个技巧
【10月更文挑战第20天】 SpringBoot以其简化配置和快速开发而受到开发者的青睐。除了基本的CRUD操作外,SpringBoot还提供了丰富的扩展接口,让我们能够更灵活地定制和扩展应用。以下是16个常用的SpringBoot扩展接口,掌握它们将帮助你写出更加优雅的代码。
42 0
|
2月前
|
SQL JSON Java
springboot 如何编写增删改查后端接口,小白极速入门,附完整代码
本文为Spring Boot增删改查接口的小白入门教程,介绍了项目的构建、配置YML文件、代码编写(包括实体类、Mapper接口、Mapper.xml、Service和Controller)以及使用Postman进行接口测试的方法。同时提供了SQL代码和完整代码的下载链接。
springboot 如何编写增删改查后端接口,小白极速入门,附完整代码
|
2月前
|
存储 前端开发 Java
springboot文件上传和下载接口的简单思路
本文介绍了在Spring Boot中实现文件上传和下载接口的简单思路。文件上传通过`MultipartFile`对象获取前端传递的文件并存储,返回对外访问路径;文件下载通过文件的uuid名称读取文件,并通过流的方式输出,实现文件下载功能。
springboot文件上传和下载接口的简单思路
|
2月前
|
存储 数据采集 Java
Spring Boot 3 实现GZIP压缩优化:显著减少接口流量消耗!
在Web开发过程中,随着应用规模的扩大和用户量的增长,接口流量的消耗成为了一个不容忽视的问题。为了提升应用的性能和用户体验,减少带宽占用,数据压缩成为了一个重要的优化手段。在Spring Boot 3中,通过集成GZIP压缩技术,我们可以显著减少接口流量的消耗,从而优化应用的性能。本文将详细介绍如何在Spring Boot 3中实现GZIP压缩优化。
301 6
|
1月前
|
存储 NoSQL Java
Spring Boot项目中使用Redis实现接口幂等性的方案
通过上述方法,可以有效地在Spring Boot项目中利用Redis实现接口幂等性,既保证了接口操作的安全性,又提高了系统的可靠性。
37 0
|
2月前
|
Java 网络架构
springboot配合thymeleaf,调用接口不跳转页面只显示文本
springboot配合thymeleaf,调用接口不跳转页面只显示文本
121 0
|
3月前
|
前端开发 小程序 Java
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
本文详细介绍了如何在SpringBoot项目中统一处理接口返回结果及全局异常。首先,通过封装`ResponseResult`类,实现了接口返回结果的规范化,包括状态码、状态信息、返回信息和数据等字段,提供了多种成功和失败的返回方法。其次,利用`@RestControllerAdvice`和`@ExceptionHandler`注解配置全局异常处理,捕获并友好地处理各种异常信息。
1101 0
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅