20191110 Spring Boot官方文档学习(4.1)
4. Spring Boot功能
4.1。Spring应用
便捷的启动方式:
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}
SpingBoot默认日志级别是INFO
。
4.1.1。启动失败
启动失败时,FailureAnalyzers
会报告错误信息。
4.1.2。延迟初始化(懒加载)
SpringApplication
允许延迟初始化应用程序。启用延迟初始化后,将根据需要创建bean,而不是在应用程序启动期间创建bean。
以下方式可以启动延迟初始化:
SpringApplicationBuilder
启动
org.springframework.boot.builder.SpringApplicationBuilder#lazyInitialization
SpringApplication
指定
org.springframework.boot.SpringApplication#setLazyInitialization
- 属性配置
spring.main.lazy-initialization=true
对bean使用延迟初始化,可以使用@Lazy
注解。
4.1.3。定制Banner
将 banner.txt
或图像文件(banner.gif
,banner.jpg
或banner.png
)放在类路径,或通过设置属性指定路径spring.banner.location
(图像为spring.banner.image.location
)。图像将转换为ASCII
在banner.txt
文件内部,可以使用以下任意占位符,参考:
变量 | 描述 |
---|---|
${application.version} |
您的应用程序的版本号,如MANIFEST.MF 中所述。例如,Implementation-Version: 1.0打印为1.0。 |
${application.formatted-version} |
您的应用程序的版本号,如MANIFEST.MF中所述,并进行了格式显示(用括号括起来,并带有前缀v)。例如(v1.0)。 |
${spring-boot.version} |
您正在使用的Spring Boot版本。例如2.2.0.RELEASE。 |
${spring-boot.formatted-version} |
您正在使用的Spring Boot版本,其格式用于显示(用括号括起来,并带有前缀v)。例如(v2.2.0.RELEASE)。 |
${Ansi.NAME} (或${AnsiColor.NAME} ,${AnsiBackground.NAME} ,${AnsiStyle.NAME} ) |
NAME是指ANSI转义代码的名称。有关详细信息,请参见AnsiPropertySource 。 |
${application.title} |
您的应用程序的标题,如MANIFEST.MF中所述。例如Implementation-Title: MyApp打印为MyApp。 |
使用 org.springframework.boot.SpringApplication#setBanner
以编程方式生成Banner
。
属性spring.main.banner-mode
指定打印Banner的方式。
打印Banner的单实例bean的id是:springBootBanner
。
4.1.4。自定义SpringApplication
传递给SpringApplication
构造函数的参数是Spring bean的配置源。在大多数情况下,这些是对@Configuration
类的引用,但它们也可以是对XML配置或应扫描的程序包的引用。
也可以通过使用application.properties
文件来配置。有关详细信息参见SpringApplication
。
有关配置选项的完整列表,参见org.springframework.boot.SpringApplication
。
4.1.5。流式Builder API
org.springframework.boot.builder.SpringApplicationBuilder
示例:
new SpringApplicationBuilder(SpringbootApplication.class).profiles("server")
.properties("transport=local").run(args);
创建ApplicationContext
层次结构时有一些限制。例如,Web组件必须包含在子上下文中,并且父和子上下文都使用相同的Environment
。
4.1.6。应用程序事件和监听器
有些事件实际上是在创建ApplicationContext
之前触发的,因此您无法将监听器注册为@Bean
来监听事件。您可以使用SpringApplication.addListeners(...)
方法或SpringApplicationBuilder.listeners(...)
方法注册它们。
如果您希望这些侦听器自动注册,而不管创建应用程序的方式如何,可以将META-INF/spring.factories
文件添加到项目中,并使用org.springframework.context.ApplicationListener
键引用您的侦听器,如以下示例所示:
org.springframework.context.ApplicationListener = com.example.project.MyListener
分析启动方法
org.springframework.boot.SpringApplication#run(java.lang.String...)
应用程序事件在您的应用程序运行时按以下顺序发送,这些事件是绑定在SpringApplication上
的SpringApplicationEvents
:
ApplicationStartingEvent
在运行开始时发送 ,但在进行任何处理之前(侦听器和初始化程序的注册除外)发送。
listeners.starting();
ApplicationEnvironmentPreparedEvent
当Environment被发送到中已知的上下文中使用,但是在创建上下文之前。
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
ApplicationContextInitializedEvent
在ApplicationContext
准备好且已调用ApplicationContextInitializers
之后,但未加载任何bean定义之前,发送。
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
listeners.contextPrepared(context);
ApplicationPreparedEvent
在刷新开始之前但在加载bean定义之后发送。
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
listeners.contextLoaded(context);
ApplicationStartedEvent
上下文已被刷新后,但是application runners
和command-line runners
被调用前,发送。
listeners.started(context);
ApplicationReadyEvent
在application runners
和command-line runners
被调用后发送。它指示该应用程序已准备就绪,可以处理请求。
listeners.running(context);
ApplicationFailedEvent
在启动异常时发送。
handleRunFailure(context, ex, exceptionReporters, listeners);
额外的事件,在ApplicationPreparedEvent
和ApplicationStartedEvent
之间发送:
ContextRefreshedEvent
在ApplicationContext
刷新后发送。WebServerInitializedEvent
在WebServer准备就绪后发送。ServletWebServerInitializedEvent
和ReactiveWebServerInitializedEvent
分别是servlet和响应式servlet的变种。
应用程序事件是通过使用Spring Framework的事件发布机制发送的。此机制的一部分确保在子级上下文中发布给侦听器的事件也会在任何祖先上下文中发布给侦听器。因此,如果您的应用程序使用SpringApplication
实例的层次结构,则侦听器可能会收到同一类型的应用程序事件的多个实例。
为了使您的侦听器能够区分其上下文的事件和后代上下文的事件,它应请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现ApplicationContextAware
来注入上下文,或者,如果侦听器是bean,则可以使用@Autowired
注入上下文。
4.1.7。Web Environment
SpringApplication
试图创建正确类型的ApplicationContext
。确定WebApplicationType
的算法非常简单:
- 如果存在
Spring MVC
,则使用AnnotationConfigServletWebServerApplicationContext
- 如果不存在
Spring MVC
且存在Spring WebFlux
,则使用AnnotationConfigReactiveWebServerApplicationContext
- 否则,使用
AnnotationConfigApplicationContext
参考源码:
org.springframework.boot.SpringApplication#run(java.lang.String...)
context = createApplicationContext();
org.springframework.boot.SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
在同一应用程序中使用Spring MVC
和Spring WebFlux
中的新功能,则默认情况下将使用Spring MVC
。可以通过调用org.springframework.boot.SpringApplication#setWebApplicationType
轻松覆盖它。也可以通过调用org.springframework.boot.SpringApplication#setApplicationContextClass
直接设置ApplicationContext
。
4.1.8。访问应用程序参数
如果您需要访问传递给SpringApplication.run(...)
的应用程序参数,则可以注入org.springframework.boot.ApplicationArgumentsBean
。ApplicationArguments
接口提供对原始String[]
参数以及已解析option和non-option参数的访问,如以下示例所示:
@Component
public class MyBean {
@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> nonOptionArgs = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}
}
Spring Boot也向Spring Environment注册了一个CommandLinePropertySource
。这样,您还可以使用@Value
注释注入单个应用程序参数。
4.1.9。使用ApplicationRunner
或CommandLineRunner
如果启动SpringApplication
后需要运行一些特定的代码,则可以实现ApplicationRunner
或CommandLineRunner
接口。这两个接口以相同的方式工作,并提供一个单一的run方法,该方法在SpringApplication.run(...)完成之前就被调用。
参考源码:
org.springframework.boot.SpringApplication#run(java.lang.String...)
callRunners(context, applicationArguments);
Runner执行时不是异步调用,而是在ApplicationStartedEvent事件和ApplicationReadyEvent之间执行。
ApplicationRunner
和CommandLineRunner
接口的不同之处在于入参不同,前者是ApplicationArguments
,后者是String...
。
如果有多个Runner,需要指定执行顺序时,可以实现org.springframework.core.Ordered
接口或使用org.springframework.core.annotation.Order
注解。
4.1.10。Application Exit
每个SpringApplication
都向JVM注册一个关闭钩子,以确保ApplicationContext
退出时正常关闭。可以使用所有标准的Spring生命周期回调(例如DisposableBean
接口或@PreDestroy
注解)。
如果希望在SpringApplication.exit()
被调用时返回特定的退出代码,则可以实现org.springframework.boot.ExitCodeGenerator
接口。然后可以将此退出代码传递给System.exit()
,以将其作为状态代码返回。
而且,Exception
实现ExitCodeGenerator
接口后,当抛出异常时,Spring Boot返回由实现的getExitCode()
方法提供的退出代码。
示例:
@SpringBootApplication
public class SpringbootApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(SpringbootApplication.class,
args)));
}
}
直接停止虚拟机不能返回特定的退出代码。
4.1.11。管理员功能
通过指定spring.application.admin.enabled
属性,可以为应用程序启用与管理员相关的功能。这将在MBeanServer平台上公开SpringApplicationAdminMXBean
。您可以使用此功能来远程管理Spring Boot应用程序。此功能对于任何服务包装器实现也可能很有用。
如果您想知道应用程序在哪个HTTP端口上运行,请通过键local.server.port
获取属性。