关于Spring Boot 的 ApplicationRunner ,CommandLineRunner 的源码探究

关于Spring Boot 的 ApplicationRunner ,CommandLineRunner 的源码探究

1.关于ApplicationRunner

// 源码
package org.springframework.boot;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/** * Interface used to indicate that a bean should <em>run</em> when it is contained within * a {@link SpringApplication}. Multiple {@link ApplicationRunner} beans can be defined * within the same application context and can be ordered using the {@link Ordered} * interface or {@link Order @Order} annotation. * * @author Phillip Webb * @since 1.3.0 * @see CommandLineRunner */
@FunctionalInterface
public interface ApplicationRunner {

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

}

2.关于CommandLineRunner

// 源码
package org.springframework.boot;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/** * 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 * @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;

}

3.说明

如果您需要在启动SpringApplication后运行某些特定代码,则可以实现ApplicationRunner或CommandLineRunner接口。两个接口以相同的方式工作并提供单个run方法,该方法在SpringApplication.run(…​)完成之前调用 。

所述CommandLineRunner接口提供访问的应用程序的参数作为一个简单的字符串数组,而ApplicationRunner使用了ApplicationArguments前面所讨论的接口。

4.关于2个接口的执行顺序

如果定义了必须以特定顺序调用的多个CommandLineRunner或ApplicationRunnerbean,
则可以另外实现 org.springframework.core.Ordered接口或使用 org.springframework.core.annotation.Order注解。

5.按照顺序执行的ApplicationRunner ,CommandLineRunner 是如何装载的

    // 源码
    private void callRunners(ApplicationContext context, ApplicationArguments args) {
        List<Object> runners = new ArrayList<>();
        // 找到所有的Runner并装到List里面
        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
        // 该sort方法会调用list的sort方法
        AnnotationAwareOrderComparator.sort(runners);
        for (Object runner : new LinkedHashSet<>(runners)) {
            // 按照排好的顺序一个一个的执行Runner
            if (runner instanceof ApplicationRunner) {
                callRunner((ApplicationRunner) runner, args);
            }
            if (runner instanceof CommandLineRunner) {
                callRunner((CommandLineRunner) runner, args);
            }
        }
    }

6.这些ApplicationRunner ,CommandLineRunner 的执行时机

// 源码
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            prepareContext(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, listeners, exceptionReporters, ex);
            throw new IllegalStateException(ex);
        }
        // 启动一系列的监听器,开始提供服务
        listeners.running(context);
        return context;
    }
    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/qq_15071263/article/details/81234737
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞