springboot源码解析-管中窥豹系列之Runner(三)

Angular入门到精通系列教程(4)- 开发环境搭建以及入手项目

一、前言

  • 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);
        }
    }
}

总共分四步:

Spring Security OAuth2.0认证授权二:搭建资源服务

  • (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

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

ABP vNext 审计日志获取真实客户端IP

给TA买糖
共{{data.count}}人
人已赞赏
经验教程

动态方法拦截(AOP)的N种解决方案

2021-1-11 9:44:00

经验教程

Angular入门到精通系列教程(4)- 开发环境搭建以及入手项目

2021-1-11 10:06:00

⚠️
免责声明:根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。 本站为个人博客非盈利性站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途,网站会员捐赠是您喜欢本站而产生的赞助支持行为,仅为维持服务器的开支与维护,全凭自愿无任何强求。本站部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。
无意侵害您的权益,请发送邮件至 momeis6@qq.com 或点击右侧 私信:momeis 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索