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

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

关于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;
        }

来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 关于Spring Boot 的 ApplicationRunner ,CommandLineRunner 的源码探究

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏