1.CommandLineRunner与ApplicationRunner接口作用

   希望在项目启动完成之前,能够初始化一些操作,针对这种需求,可以考虑实现如下两个接口

   CommandLineRunner与ApplicationRunner接口的使用及源码解析_初始化

 

  注:CommandLineRunner、ApplicationRunner 接口是在容器启动成功后的最后一步回调(类似开机自启动)。

 

2.CommandLineRunner接口

   源码:

     CommandLineRunner与ApplicationRunner接口的使用及源码解析_初始化_02

 

    官方doc:​​Interface used to indicate that a bean should run when it is contained within a SpringApplication. ​

​        Multiple CommandLineRunner beans can be defined within the same application context and can be ordered using the Ordered interface or Order @Order annotation.​

 

    接口被用作将其加入spring容器中时执行其run方法。多个CommandLineRunner可以被同时执行在同一个spring上下文中并且执行顺序是以order注解的参数顺序一致。

 

​ If you need access to ApplicationArguments instead of the raw String array consider using ApplicationRunner.​

如果你需要访问ApplicationArguments去替换掉字符串数组,可以考虑使用ApplicationRunner类。

 

   实例demo

   定义一个ServerStartedReport实现CommandLineRunner,并纳入到srping容器中进行处理

   CommandLineRunner与ApplicationRunner接口的使用及源码解析_spring_03

 

    定义一个ServerSuccessReport实现CommandLineRunner,并纳入到spring容器处理

    CommandLineRunner与ApplicationRunner接口的使用及源码解析_ide_04

 

    启动类测试,也可以直接在spring容器访问该值

    CommandLineRunner与ApplicationRunner接口的使用及源码解析_ide_05

 

    配置参数,然后执行启动类

    CommandLineRunner与ApplicationRunner接口的使用及源码解析_javad_06

 

    打印结果

    CommandLineRunner与ApplicationRunner接口的使用及源码解析_ide_07

 

     总结:从结果可以看到,启动后可以通过注解ORDER实现一个顺序

     

 3.ApplicationRunner接口

    源码:

       CommandLineRunner与ApplicationRunner接口的使用及源码解析_初始化_08

 

   和​​CommandLineRunner接口的区别:​

         发现二者的官方javadoc一样,区别在于接收的参数不一样。​​CommandLineRunner​​的参数是最原始的参数,没有做任何处理。​​ApplicationRunner​​的参数是​​ApplicationArguments​​,是对原始参数做了进一步的封装。

         ​​ApplicationArguments​​是对参数(main方法)做了进一步的处理,可以解析--name=value的,我们就可以通过name来获取value(而CommandLineRunner只是获取--name=value)

         源码:

         CommandLineRunner与ApplicationRunner接口的使用及源码解析_初始化_09

 

    实例demo

    CommandLineRunner与ApplicationRunner接口的使用及源码解析_初始化_10

 

     CommandLineRunner与ApplicationRunner接口的使用及源码解析_初始化_11

 

       CommandLineRunner与ApplicationRunner接口的使用及源码解析_ide_12

 

       

    总结

          用户使用CommandLineRunner或者ApplicationRunner接口均可实现应用启动初始化某些功能的需求,如果希望对参数有更多的操作,则可以选择实现ApplicationRunner接口。

 

 4.源码解析(如何被调用)

    CommandLineRunner、ApplicationRunner执行流程源码分析

    用户只要实现这两个接口,其中的run方法就会在项目启动时候被自动调用,那么究竟是在什么时候调用的呢?

    下面可以看一下Application的启动流程SpringApplication.run(args)

     CommandLineRunner与ApplicationRunner接口的使用及源码解析_ide_13

 

     CommandLineRunner与ApplicationRunner接口的使用及源码解析_javad_14

 

      this.afterRefresh(context, applicationArguments)方法(CommandLineRunner或者ApplicationRunner接口的run被调用的地方)

      CommandLineRunner与ApplicationRunner接口的使用及源码解析_spring_15

 

      跟踪context.getBeansOfType()方法,具体实现在类DefaultListableBeanFactory中

      CommandLineRunner与ApplicationRunner接口的使用及源码解析_javad_16

 

     CommandLineRunner与ApplicationRunner接口的使用及源码解析_spring_17

 

     CommandLineRunner与ApplicationRunner接口的使用及源码解析_javad_18

 

     总结:通过以上分析可知,实现这两个接口的类,在​​ApplicationContext.run()​​方法里被执行。