springboot

来源:互联网 发布:java九九乘法表上三角 编辑:程序博客网 时间:2024/06/01 10:23

ApplicationRunner and CommandLineRunner

开发中可能会遇到这样的需求,需要在容器启动的时候执行一些内容,比如读取配置文件,数据库操作等等。SpringBoot给我们提供了两个接口来帮助我们定制这种需求,这两个接口分别为CommandLineRunner和ApplicationRunner,他们会在容器启动完成后执行。这两个接口中有一个run方法,我们只需要实现这个方法即可。这两个接口的不同之处在于:ApplicationRunner中run方法的参数为ApplicationArguments,而CommandLineRunner接口中run方法的参数为String数组。

public interface ApplicationRunner {    void run(ApplicationArguments var1) throws Exception;}public interface CommandLineRunner {    void run(String... var1) throws Exception;}

1、 在SpringApplication的启动方法run中,完成上下文刷新后,会执行afterRefresh 方法

public ConfigurableApplicationContext run(String... args) {        ...        try {            ...            this.prepareContext(context, environment, listeners, ex, printedBanner);            this.refreshContext(context);            this.afterRefresh(context, ex);            ...            }            return context;        } catch (Throwable var9) {           ...        }    }

2、 在afterRefresh方法中,会调用两种Runners,主要就是查找上下文中所有实现了ApplicationRunner 和 CommandLineRunner接口的bean,然后执行其run方法,这样我们就有机会定制自己的代码。

protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {        this.callRunners(context, args);    }    private void callRunners(ApplicationContext context, ApplicationArguments args) {        ArrayList runners = new ArrayList();        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());        AnnotationAwareOrderComparator.sort(runners);        Iterator var4 = (new LinkedHashSet(runners)).iterator();        while(var4.hasNext()) {            Object runner = var4.next();            if(runner instanceof ApplicationRunner) {                this.callRunner((ApplicationRunner)runner, args);            }            if(runner instanceof CommandLineRunner) {                this.callRunner((CommandLineRunner)runner, args);            }        }    }

3、 分别实现ApplicationRunner 和 CommandLineRunner如下:

public class MyApplicationRunner implements ApplicationRunner {    private final Logger logger = LoggerFactory.getLogger(MyApplicationRunner.class);    @Override    public void run(ApplicationArguments applicationArguments) throws Exception {        logger.info("MyApplicationRunner.run() is invoked! " + applicationArguments);    }}
public class MyCommandLineRunner implements CommandLineRunner {    private final Logger logger  = LoggerFactory.getLogger(MyCommandLineRunner.class);    @Override    public void run(String... strings) throws Exception {        logger.info("MyCommandLineRunner.run() is invoked! " + strings);    }}

4、将上述实现的类,配置为bean

@SpringBootApplicationpublic class Application {    @Bean    public MyCommandLineRunner startupRunner(){        return new MyCommandLineRunner();    }    @Bean    public MyApplicationRunner myApplicationRunner(){        return new MyApplicationRunner();    }    public static void main(String[] args) {        SpringApplication app = new SpringApplication(Application.class);        app.setBannerMode(Banner.Mode.OFF);        app.run(args);    }}

5、执行main方法,可以看到输出如下内容:

...2017-08-25 16:31:12.150  INFO 58583 --- [           main] c.s.boot.runner.MyApplicationRunner      : MyApplicationRunner.run() is invoked! org.springframework.boot.DefaultApplicationArguments@70925b452017-08-25 16:31:12.150  INFO 58583 --- [           main] c.s.boot.runner.MyCommandLineRunner      : MyCommandLineRunner.run() is invoked! [Ljava.lang.String;@1b9ea3e32017-08-25 16:31:12.152  INFO 58583 --- [           main] com.spring.boot.Application             : Started Application in 11.905 seconds (JVM running for 12.237)
原创粉丝点击