一、前言

  • 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. CobaltStrike 生成office宏病毒进行钓鱼攻击

    关于WORD宏: 在百度百科上有: 宏是一个批量处理程序命令,正确地运用它可以提高工作效率.微软的office软件允许用户自己编写,叫VBA的脚本来增加其灵活性,进一步扩充它的能力.如完打开word文 ...

  2. 对flask的学习

    任务需求:一个登录,注册页面 任务环境:pycharm 2018 专业版,python3.7,win 10专业版 ------------------------------------------- ...

  3. 软工个人项目 ——wc.exe

    1.GitHub项目地址 https://github.com/k8kiw/WordCount 2.PSP预计时间 PSP2.1 Personal Software Process Stages 预估 ...

  4. java性能问题排查提效脚本工具

    在性能测试过程中,往往会出现各种各样的性能瓶颈.其中java常见瓶颈故障模型有cpu资源瓶颈:文件IO瓶颈:网络IO瓶颈:内存资源瓶颈:资源消耗不高程序本身执行慢等场景模型. 如何快速定位分析这些类型 ...

  5. 【题解】「UVA10116」Robot Motion

    Simple Translation 让你模拟一个机器人行走的过程,如果机器人走入了一个循环,输出不是循环的长度和是循环的长度,如果最终走出来了,输出走的步数. Solution 直接模拟即可,本题难 ...

  6. (原创)nginx反向代理上网,使docker可以拉取镜像

    转载请注明出处:饭饭博客:https://www.cnblogs.com/zzf0305/p/9602107.html 摘语:参考了N多大侠的资料,终于将自己的环境配置起来了.站在众多巨人的肩膀进行总 ...

  7. ORA-01578: ORACLE data block corrupted (file # 3, block # 1675)

    警告日志中发现如下报错信息: ORA-01578: ORACLE data block corrupted (file # 3, block # 1675)ORA-01110: data file 3 ...

  8. 解决IDEA Maven下载依赖包速度慢问题

    右键项目,maven选项,"Open setting.xml"或"Create setting.xml",在 mirrors 节点添加下面代码. <mir ...

  9. 【教程】IDEA创建Maven项目并整合Tomcat发布,问题解决大全

    一篇入门教程 一.创建项目并运行 参考这个视频,能顺利运行 helloworld ,本人用的 IDEA2020.2.3 .jdk11 .Tomcat9 .Maven3.6 bilibili-IDEA( ...

  10. css3选择器归类整理---基本选择器和属性选择器

    css3选择器分类 CSS3选择器分类如下图所示 选择器的语法 1.基本选择器 类型 代码 功能描述 通配选择器 *{ margin: 0; padding: 0; border: none; } 选 ...