两个Runner初始化器
两个Runner初始化器——主要作用是对component组件来执行初始化
这里的Component组件我理解为是被@Component注解修饰的类
@Component //用这个注解修饰的类,意味着这个类是spring容器中的一个组件,springboot应用会自动加载该组件。
两个Runner初始化器,实际上就是两个接口,ApplicationRunner接口和CommandLineRunner接口。这两个接口功能大致相同,实现的方法都是run()方法。
作用:
在springApplication的run()方法完成之前,这两个接口的实现类里面的run()方法会被自动调用,因此,这两个实现类非常适合在springboot项目启动之后、对外提供服务之前执行一些特定的初始化处理。
和容器初始化器的功能有些相似。不是针对容器进行初始化,而是针对应用来进行初始化。所以也叫他们两个为初始化器。
在SpringApplication的run()完成之前,Spring Boot会自动调用实现了ApplicationRunner或CommandLineRunner接口的类里面的run()方法。
换句话来说,如果一个被 @Component注解 修饰的类实现了ApplicationRunner或CommandLineRunner接口,Spring boot将会在SpringApplication的run()完成之前,自动调用该实现类里面的重写的run()方法
相当于一个钩子方法,专门用于在SpringApplication的run()完成之前,执行Component组件的初始化方法。
这里的Component组件我理解为是被@Component注解修饰的类。
——它是依赖于Spring Boot应用的本身的生命周期的传统Spring本身可以对组件执行初始化
——实现InitalizationBean接口,或通过init-method属性来指定初始化方法。
——这种方式所依赖的是Spring容器中Bean的生命周期行为。
代码示例:
program arguments --> 程序的命令行参数
aaa, bbb, --cc=ddd
aaa是一个命令参数,bbb是一个命令参数 , --cc=ddd 也是一个参数,叫选项参数,这个–cc=ddd参数是会被springboot自动解析的。
▲ 运行Spring Boot应用的两种命令行参数A。 传统的参数,直接列出一个一个的参数B。 双横线开头的选项参数, 这种参数包括了选项名和选项值。这种选项参数实际上就是对Spring Boot进行配置的参数,地位相当于application.properties文件配置,且优先级更高。
这种选项参数实际上就是对Spring Boot进行配置的参数,地位相当于application.properties文件配置,且优先级更高,会覆盖了application.properties 配置文件。
代码解释:
这里的代码只是演示项目启动时,在启动类springApplication的run()方法完成之前,ApplicationRunner接口和CommandLineRunner接口这两个接口的实现类Dog和Cat里面的run()方法会被自动调用。
具体要怎么在springApplication的run()方法完成之前做哪些额外操作或配置,需要根据实际业务去执行。
因为ApplicationRunner接口和CommandLineRunner接口的功能大致相同,区别就是ApplicationRunner接口的run方法使用 参数类型ApplicationArguments 获取参数更加方便。
下面的代码就是在演示ApplicationRunner接口通过ApplicationArguments获取参数的便利性。
在Program arguments 设置的配置的作用跟在 application.properties 配置文件设置的功能一样,但是在 Program arguments 这里设置的优先级高于 application.properties配置文件。
总结:主要演示两个Runner初始化器的实现方式,并对这两个初始化器获取参数进行比较。因为即使没有这两个初始化器,在启动配置那里对Program arguments进行的配置也没有任何影响,依然生效。所以这代码只是演示获取参数的便利性。就是能获取项目在启动的时候在Program arguments的一些配置。
其他的目前看不出有什么作用,因为也获取不到application.properties的配置。
ApplicationArguments 解释
简单来说: 只要你的任意组件(@Component注解修饰的类)希望访问Spring Boot应用的运行参数,都可以定义一个ApplicationArguments类型的成员变量,并使用@Autowired修饰它,Spring将会完成依赖注入。
什么是ApplicationArguments ?
ApplicationArguments 是Runner初始化器---->ApplicationRunner接口实现类的Run方法里面的参数类型。
上面介绍的是这个ApplicationArguments 可以非常方便的访问运行参数(这里的运行参数是指项目启动的时候的一些配置参数)。而且不局限于在Runner初始化器中使用。
只要这个类添加了@Component注解,那么这个类(也可以叫组件) 就可以使用这个ApplicationArguments 对象来获取一些运行参数。通过依赖注入的方式使用。
【注意:】 由于依赖注入,一定是在对象被创建出来之后才会完成,因此不能在组件的构造器中调用ApplicationArguments来访问应用程序的运行参数。
因为这个类要先通过构造器创建出来,再进行对这个ApplicationArguments依赖注入来使用,如果在构造器里面调用ApplicationArguments对象的一些方法,那么会因为对象还没创建出来,所以还没有到注入ApplicationArguments对象这一步,所以其实还没有这个依赖可以使用,就会出问题。我们可以在自己定义的方法中来调用ApplicationArguments。
代码示例:
只要我们的类想要访问到springboot项目的运行参数,就可以通过ApplicationArguments这个API来获取。记得这个类得用@Component注解修饰。
项目的运行参数,可以在这里设置添加。
springboot创建非web应用
当Spring Boot应用带有Spring MVC或Spring WebFlux依赖时,Spring Boot都会自动创建Web应用。
要显式创建非Web应用,可设置:▲方法1: 通过SpringApplication对象来设置
var application = new SpringApplication(App.class);
// 设置创建非Web应用
application.setWebApplicationType(WebApplicationType.NONE);▲ 方法2:用SpringApplicationBuilder通过流式编程来设置new SpringApplicationBuilder().sources(App.class)// 创建非Web应用.web(WebApplicationType.NONE).run();▲ WebApplicationType.NONE有3个枚举值:- SERVLET: 对应Spring MVC的默认值。- REACTIVE:对应于Spring WebFlux的默认值。- NONE:非Web应用
【备注】:如果使用SpringApplication的静态run()方法来启动Spring Boot应用,那将意味着一切都用默认的行为。
方法1:通过SpringApplication对象来设置
方法2:用SpringApplicationBuilder通过流式编程来设置
代码:
cat
package cn.ljh.boot.domain;import lombok.Data;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;import java.util.Arrays;@Data
@Component
public class Cat implements ApplicationRunner {private String addr;//ApplicationArguments 可以更方便的访问运行springboot的命令行参数//这个run方法用于对该Bean(这个Cat类)执行初始化,此处的args就代表了运行该应用的命令行参数@Overridepublic void run(ApplicationArguments args) throws Exception {System.err.println("=====对Cat执行初始化=====");//获取原始的参数System.err.println("Cat的run方法,args命令行参数:" + Arrays.toString(args.getSourceArgs()));//获取非选项参数System.err.println("Cat的run方法,获取args里面的非选项参数:"+args.getNonOptionArgs());//获取选项参数名System.err.println("Cat的run方法,获取args里面的【选项参数名】:"+args.getOptionNames());//根据选项名获取对应的选项值for (String optionName : args.getOptionNames()) {System.err.println("Cat的run方法,获取args里面的【选项参数值】: 选项参数名:"+optionName + " 选项参数值:" +args.getOptionValues(optionName));}}
}
dog
package cn.ljh.boot.domain;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;import java.util.Arrays;@Data
@Component //用这个注解修饰,意味着这个类是spring容器中的一个组件,springboot应用会自动加载该组件。
public class Dog implements CommandLineRunner {//将配置文件(myEnvironment.properties)里面的 myDogName 属性的值注入到这个字段里面@Value("${myDogName}")private String name;//将配置文件(myEnvironment.properties)里面的 myDogAge 属性的值注入到这个字段里面@Value("${myDogAge}")private int age;//无参构造器public Dog(){System.out.println("===创建Dog对象===");}//实现CommandLineRunner接口后要重写的方法//这个run方法用于对该Bean(这个Dog类)执行初始化,此处的args就代表了运行该应用的命令行参数@Overridepublic void run(String... args) throws Exception {System.err.println("=====对Dog执行初始化=====");System.err.println("Dog的run方法的args参数:"+Arrays.toString(args));}
}