zoukankan      html  css  js  c++  java
  • SpringBoot的启动加载器

    SpringBoot的启动加载器

    1.概念

    SpringBoot的启动加载器是SpringBoot 容器启动完成后被启动的类的一种机制。

    可以实现项目启动后需要默认调用的功能。

    2. 实现

    2.1 两种方式

    - 实现 CommandLineRunner接口
    - 实现 ApplicationRunner接口
    

    2.2 调用顺序的实现

    • 使用 order 注解

    3. 实现 CommandLineRunner 接口的代码

    @Component
    public class FirstCommandlineRunner implements CommandLineRunner {
        @Override
        public void run(String... args) throws Exception {
            System.out.println(">>>> startup first runner <<<<<");
        }
    }
    

    ①实现 CommandLineRunner 接口,② 重新 run方法,③ 添加Component 注解

    4. 实现ApplicationRunner 接口的代码

    @Component
    @Order(1)
    public class FirstApplicationRunner implements ApplicationRunner {
        @Override
        public void run(ApplicationArguments args) throws Exception {
            System.out.println(">>>>>  First Application runner start <<<<<<");
        }
    }
    

    ①实现ApplicationRunner 接口,②重新 run 方法 ③添加Component 注解

    如果要实现先后顺序添加 Order(优先级)

    5. 启动器的实现原理

    开发人员实现 ApplicationRunner 接口或者 CommandLineRunner 接口重写 run 方法,run 方法为启动器执行的方法,可以放入业务相关的内容。

    容器在启动中调用 SpringApplication的 run() 方法内容器初始化相关的方法调用完成后 调用 callRunners 方法对启动器进行获取及调用,

    callRunners 方法传入 applicationContext 对象和参数,方法内获取实现了上面两个接口的类然后获取对应的方法及参数实现对启动类的调用。

    • 容器 run 方法调用完成后调用 call runners 方法
    SpringApplication 类中 run() 方法
    listeners.started(context);
    callRunners(context, applicationArguments);
    
    • callRunners 方法具体实现
    private void callRunners(ApplicationContext context, ApplicationArguments args) {
       List<Object> runners = new ArrayList<>();
      runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
      runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
       AnnotationAwareOrderComparator.sort(runners);
       for (Object runner : new LinkedHashSet<>(runners)) {
          if (runner instanceof ApplicationRunner) {
             callRunner((ApplicationRunner) runner, args);
          }
          if (runner instanceof CommandLineRunner) {
             callRunner((CommandLineRunner) runner, args);
          }
       }
    }
    
    • 实现了 ApplicationRunner接口的调用
    private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
       try { // args 为对象
          (runner).run(args);
       }
       catch (Exception ex) {
          throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
       }
    }
    
    • 实现了 CommandLineRunner 接口的调用
    private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
       try { // args.getSourceArgs() 为string 数组
          (runner).run(args.getSourceArgs());
       }
       catch (Exception ex) {
          throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
       }
    }
    

    6. 问题

    1. 启动加载器如何实现?
    2. 启动加载器实现的异同点?
    3. 启动加载器的调用时机?
  • 相关阅读:
    【.NET深呼吸】Zip文件操作(1):创建和读取zip文档
    【Win10 应用开发】实现数据的增量加载
    【Win10 应用开发】使用“实时可视化树”工具查看应用界面元素
    将中文字符串分割为数组 解决str_split中文乱码php
    Mac搭建PHP+rabbitMQ环境
    常用笔记:PHP
    常用笔记:MySQL
    常用笔记:Linux
    常用笔记:Web前端
    常用笔记:工具使用
  • 原文地址:https://www.cnblogs.com/vawa/p/13266571.html
Copyright © 2011-2022 走看看