Spring Boot - ApplicationRunner && CommandLineRunner扩展接口

简介: ApplicationRunner && CommandLineRunner扩展接口

@[toc]

在这里插入图片描述


Pre

Spring Boot - 扩展接口一览

在这里插入图片描述


org.springframework.boot.CommandLineRunner

/**
 * Interface used to indicate that a bean should <em>run</em> when it is contained within
 * a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined
 * within the same application context and can be ordered using the {@link Ordered}
 * interface or {@link Order @Order} annotation.
 * <p>
 * If you need access to {@link ApplicationArguments} instead of the raw String array
 * consider using {@link ApplicationRunner}.
 *
 * @author Dave Syer
 * @since 1.0.0
 * @see ApplicationRunner
 */
@FunctionalInterface
public interface CommandLineRunner {

    /**
     * Callback used to run the bean.
     * @param args incoming main method arguments
     * @throws Exception on error
     */
    void run(String... args) throws Exception;

}

在这里插入图片描述

接口也只有一个方法:run(String... args)

如果有多个CommandLineRunner,可以利用@Order来进行排序, 按照@Order中的value值从小到大依次执行。


使用场景

  • 触发时机为整个项目启动完毕后(执行时机为容器启动完成的时候),自动执行。
  • 扩展此接口,进行启动项目之后一些业务的预处理。

源码解析

在这里插入图片描述

    /**
     * Run the Spring application, creating and refreshing a new
     * {@link ApplicationContext}.
     * @param args the application arguments (usually passed from a Java main method)
     * @return a running {@link ApplicationContext}
     */
    public ConfigurableApplicationContext run(String... args) {
        // 创建并启动计时监控类
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        DefaultBootstrapContext bootstrapContext = createBootstrapContext();
        ConfigurableApplicationContext context = null;
        configureHeadlessProperty();
        // 创建所有 Spring 运行监听器并发布应用启动事件
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);
        try {
            // 处理 args 参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            
            // 准备环境
            ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            configureIgnoreBeanInfo(environment);
            
            Banner printedBanner = printBanner(environment);
            // 创建应用上下文
            context = createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            // 准备应用上下文
            prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            // 刷新应用上下文
            refreshContext(context);
            // 应用上下文刷新之后的事件的处理
            afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
            }
            // 发布应用上下文启动完成事件
            listeners.started(context);]
            // 执行所有 Runner 运行器
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, listeners);
            throw new IllegalStateException(ex);
        }

        try {
            
             // 发布应用上下文就绪事件
            listeners.running(context);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }

继续 this.callRunners(context, applicationArguments);

核心方法 callRunners

private void callRunners(ApplicationContext context, ApplicationArguments args) {
        //将实现ApplicationRunner和CommandLineRunner接口的类,存储到集合中
        List<Object> runners = new ArrayList<>();
        // 从Spring容器中查找类型为ApplicationRunner的Bean
        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
        // 从Spring容器中查找类型为CommandLineRunner的Bean
        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
        
         //按照加载先后顺序排序
        AnnotationAwareOrderComparator.sort(runners);
        
        //调用执行
        for (Object runner : new LinkedHashSet<>(runners)) {
            //如果是ApplicationRunner的实例
            if (runner instanceof ApplicationRunner) {
                callRunner((ApplicationRunner) runner, args);
            }
             //如果是CommandLineRunner的实例
            if (runner instanceof CommandLineRunner) {
                callRunner((CommandLineRunner) runner, args);
            }
        }
    }
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
        try {
            //调用各个实现类中的逻辑实现
            (runner).run(args);
        }
        catch (Exception ex) {
            throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
        }
    }

OK, CLEAR
在这里插入图片描述


扩展示例

ApplicationRunner

package com.artisan.bootspringextend.testextends;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;

/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/12/7 11:49
 * @mark: show me the code , change the world
 */

@Slf4j
@Configuration
public class ExtendApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info(">>>>>>>ExtendApplicationRunner#run called {}",args);

    }
}
    

----------

CommandLineRunner

package com.artisan.bootspringextend.testextends;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;

/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2022/12/7 9:01
 * @mark: show me the code , change the world
 */

@Slf4j
@Configuration
public class ExtendCommandLineRunner  implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info(">>>>>>>ExtendCommandLineRunner#run called {}",args);
    }
}
    

在这里插入图片描述

在这里插入图片描述

相关文章
|
5月前
|
安全 NoSQL Java
SpringBoot接口安全:限流、重放攻击、签名机制分析
本文介绍如何在Spring Boot中实现API安全机制,涵盖签名验证、防重放攻击和限流三大核心。通过自定义注解与拦截器,结合Redis,构建轻量级、可扩展的安全防护方案,适用于B2B接口与系统集成。
826 3
|
8月前
|
算法 网络协议 Java
Spring Boot 的接口限流算法
本文介绍了高并发系统中流量控制的重要性及常见的限流算法。首先讲解了简单的计数器法,其通过设置时间窗口内的请求数限制来控制流量,但存在临界问题。接着介绍了滑动窗口算法,通过将时间窗口划分为多个格子,提高了统计精度并缓解了临界问题。随后详细描述了漏桶算法和令牌桶算法,前者以固定速率处理请求,后者允许一定程度的流量突发,更符合实际需求。最后对比了各算法的特点与适用场景,指出选择合适的算法需根据具体情况进行分析。
747 56
Spring Boot 的接口限流算法
|
XML Java 数据格式
探索Spring之利剑:ApplicationContext接口
本文深入介绍了Spring框架中的核心接口ApplicationContext,解释了其作为应用容器的功能,包括事件发布、国际化支持等,并通过基于XML和注解的配置示例展示了如何使用ApplicationContext管理Bean实例。
623 6
|
8月前
|
Java API 网络架构
基于 Spring Boot 框架开发 REST API 接口实践指南
本文详解基于Spring Boot 3.x构建REST API的完整开发流程,涵盖环境搭建、领域建模、响应式编程、安全控制、容器化部署及性能优化等关键环节,助力开发者打造高效稳定的后端服务。
1166 1
|
11月前
|
前端开发 Java 数据库连接
Spring MVC 扩展和SSM框架整合
通过以上步骤,我们可以将Spring MVC扩展并整合到SSM框架中。这个过程包括配置Spring MVC和Spring的核心配置文件,创建控制器、服务层和MyBatis的Mapper接口及映射文件。在实际开发中,可以根据具体业务需求进行进一步的扩展和优化,以构建更加灵活和高效的企业级应用程序。
303 5
|
监控 Java Spring
SpringBoot:SpringBoot通过注解监测Controller接口
本文详细介绍了如何通过Spring Boot注解监测Controller接口,包括自定义注解、AOP切面的创建和使用以及具体的示例代码。通过这种方式,可以方便地在Controller方法执行前后添加日志记录、性能监控和异常处理逻辑,而无需修改方法本身的代码。这种方法不仅提高了代码的可维护性,还增强了系统的监控能力。希望本文能帮助您更好地理解和应用Spring Boot中的注解监测技术。
480 16
|
Java 开发者 Spring
精通SpringBoot:16个扩展接口精讲
【10月更文挑战第16天】 SpringBoot以其简化的配置和强大的扩展性,成为了Java开发者的首选框架之一。SpringBoot提供了一系列的扩展接口,使得开发者能够灵活地定制和扩展应用的行为。掌握这些扩展接口,能够帮助我们写出更加优雅和高效的代码。本文将详细介绍16个SpringBoot的扩展接口,并探讨它们在实际开发中的应用。
452 1
|
4月前
|
JavaScript Java 关系型数据库
基于springboot的项目管理系统
本文探讨项目管理系统在现代企业中的应用与实现,分析其研究背景、意义及现状,阐述基于SSM、Java、MySQL和Vue等技术构建系统的关键方法,展现其在提升管理效率、协同水平与风险管控方面的价值。
|
4月前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。

热门文章

最新文章