一、前言

  • Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去。
  • 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot源码管中窥豹系列。

二、Runner

  • 假如我们想在springboot项目启动完成之后,做点什么,我们应该怎么办呢?
  • 注意我们可以写在bean的初始化方法里面(我们后面讲),但是我们要用到其它已经加载了的bean的能力,又怎么办呢?
  • 当然加顺序,加依赖也能解决,就是麻烦

这一节我们讨论一下springboot项目的Runner,Runner是在spring加载完毕执行的,springboot有两种Runner:

  • ApplicationRunner
  • CommandLineRunner
@FunctionalInterface
public interface ApplicationRunner { void run(ApplicationArguments args) throws Exception; } @FunctionalInterface
public interface CommandLineRunner { void run(String... args) throws Exception; }
  • 两种除了参数不同,其它没区别
  • ApplicationArguments是对传参数组的封装,本质也没区别
  • 只有执行顺序上有区别,下面源码会看到

三、用法

实现接口就可以了

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; @Component
public class HelloRunner implements ApplicationRunner { @Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("hello runner");
}
}
  • 因为这时候spring已经加载完毕,你可以引入其它bean
  • 启动项目,你会发现在日志最下方打印了上面的话

四、源码解读

我们直接找SpringApplication类的run方法,想看整体框架的去第一节。

public ConfigurableApplicationContext run(String... args) {

    ...

    try {

        ...

        callRunners(context, applicationArguments);

        ...

    }
catch (Throwable ex) { ... } ... return context;
}

我们直接定位到callRunners方法。

private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
// (1) 找到ApplicationRunner的实现类,加到list里面
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
// (2) 找到CommandLineRunner的实现类,加到list里面
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
// (3) 排序
AnnotationAwareOrderComparator.sort(runners);
// (4) 钩子回调
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}

总共分四步:

  • (1) 找到ApplicationRunner的实现类,加到list里面

  • (2) 找到CommandLineRunner的实现类,加到list里面

  • (3) 排序

  • (4) 钩子回调

我们看一下canllRunner

private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
} private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
  • 除了传参方式,都一样。
  • 上面说的执行顺序问题,是先添加的ApplicationRunner,如果只有@Component,先执行ApplicationRunner

欢迎关注公众号:丰极,更多技术学习分享。

springboot源码解析-管中窥豹系列之Runner(三)的更多相关文章

  1. springboot源码解析-管中窥豹系列

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  2. springboot源码解析-管中窥豹系列之BeanDefine如何加载(十三)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  3. springboot源码解析-管中窥豹系列之BeanPostProcessor(十二)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  4. springboot源码解析-管中窥豹系列之bean如何生成?(十四)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  5. springboot源码解析-管中窥豹系列之web服务器(七)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  6. springboot源码解析-管中窥豹系列之BeanDefinition(八)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  7. springboot源码解析-管中窥豹系列之自动装配(九)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  8. springboot源码解析-管中窥豹系列之EnableXXX(十)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  9. springboot源码解析-管中窥豹系列之BeanFactoryPostProcessor(十一)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

随机推荐

  1. Java基础学习之基础概念与环境搭建(1)

    1.Java基础概念 1.1.Java语言的特点 Java语言是简单易学的 Java语言是面向对象(封装.继承和多态) Java语言是平台无关的(一次编译,到处运行) Java语言是可靠的.安全的(异 ...

  2. Jenkins 如何实现 拷贝文件到网络共享目录

    在使用jenkins中,发现拷贝文件时,不能在脚本中直接添加脚本实现. 我实现的一种方法,希望能对您有用. net use y: \\server_name\workspace "passw ...

  3. [原创] C# 金额大写

    突然要用到这个功能.也网上找了下. 最后还是自动动手写了一个. 估计这个还是有人要要的,所以顺便发出来吧. 引用保留 https://www.cnblogs.com/goldli/p/14105832 ...

  4. dp斜率优化

    算法-dp斜率优化 前置知识: 凸包 斜率优化很玄学,凭空讲怎么也讲不好,所以放例题. [APIO2014]序列分割 [APIO2014]序列分割 给你一个长度为 \(n\) 的序列 \(a_1,a_ ...

  5. Java IO源码分析(二)——ByteArrayInputStream 和 ByteArrayOutputStream

    简介 ByteArrayInputStream 是字节数组输入流,它继承于InputStream. 它的内部数据存储结构就是字节数组. ByteArrayOutputStream是字节数组输出流,它继 ...

  6. 1、MyCat入门

    1.Mycat简介 [1].Mycat是什么 Mycat 是数据库中间件 [2].why使用Mycat ①.Java与数据库紧耦合 ②.高访问量高并发对数据库的压力 ③.读写请求数据不一致 [3].数 ...

  7. 网络 IO 模型简单介绍

    一.同步阻塞 IO(BIO) 当用户线程调用了 read 系统调用,内核(kernel)就开始了 IO 的第一个阶段:准备数据.很多时候,数据在一开始还没有到达(比如,还没有收到一个完整的Socket ...

  8. hadoop_MapReduce_idea上打jar包,在虚拟机上运行

    打包前的介绍和准备工作 指定主类可以在运行jar包的时候不用输入要运行哪一个类,直接就可以运行了 指定主类 编辑jar 的信息 修改jar包的名称 build Complete!!! MapReduc ...

  9. 多年总结IDEA 使用技巧 (建议收藏!)

    很长一段时间没有更新了,前段时间转测试了,浪费了一些时间,终于可以写文章了,今天来写一下之前自己开发的一些习惯,因为自己本身自己是一个极简主义所以 开发喜欢这样:. 全屏显示 我们可以使用[Prese ...

  10. 高可用K8S构建3master+3node+keepalived+haproxy

    视频地址:https://www.bilibili.com/video/BV1w4411y7Go?p=66 所需安装包在视频评论区 安装准备 系统: CentOS-7-x86_64-Minimal-1 ...