16 Spring Boot 应用启动功能
SpringApplication
该类提供了一种从main()
方法启动的 Spring 应用程序的便捷方法。在许多情况下,可以委托给静态方法SpringApplication.run
,如下例所示:
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}
应用程序启动时,应看到类似于以下输出的内容:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v2.1.17.BUILD-SNAPSHOT
2019-04-31 13:09:54.117 INFO 56603 --- [ main] o.s.b.s.app.SampleApplication : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2019-04-31 13:09:54.166 INFO 56603 --- [ main] ationConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2019-04-01 13:09:56.912 INFO 41370 --- [ main] .t.TomcatServletWebServerFactory : Server initialized with port: 8080
2019-04-01 13:09:57.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running for 3.658)
默认情况下,将显示日志记录消息,包括一些相关的启动详细信息,例如启动应用程序的用户。如果需要 以外的日志级别,可以设置它,如第26.4 节"日志级别"中所述。应用程序版本使用主应用程序类包的实现版本确定。可以通过设置为 来关闭启动信息日志记录。这也将关闭应用程序的活动配置文件的日志记录。
spring.main.log-startup-info=false
若要在启动期间添加其他日志记录,可以在 的子类中重写 。
logStartupInfo(boolean)
SpringApplication
16.1 启动失败
如果应用程序无法启动,则注册者将有机会提供专用错误消息和解决问题的具体行动。例如,如果在端口上启动 Web 应用程序,并且该端口已在使用中,您应该会看到类似于以下消息的内容:FailureAnalyzers
8080
***************************
APPLICATION FAILED TO START
***************************
Description:
Embedded servlet container failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
Spring Boot 提供了许多实现,您可以添加自己的FailureAnalyzer
如果没有故障分析器能够处理异常,您仍然可以显示完整的条件报告,以更好地了解哪里出了问题。为此,您需要启用调试
属性或启用DEBUG
日志记录。org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
例如,如果使用 运行应用程序,可以按如下所示启用java -jar
debug
属性:
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
16.2 自定义横幅
可以通过将banner.txt
文件添加到类路径或将属性spring.banner.location
设置为此类文件的位置来更改启动时打印的横幅。如果文件具有 UTF-8 以外的编码,您可以设置 spring.banner.charset
。除了文本文件外,还可以向类路径添加图像文件 banner.gif
banner.jpg
banner.png
或设置属性spring.banner.image.location
。图像将转换为 ASCII 艺术表示形式,并打印在任何文本横幅之上。
在文件banner.txt
内,您可以使用以下任何占位符:
表 16.1.横幅变量
变量 | 描述 |
---|---|
${application.version} | 应用程序的版本号,如 中声明的。例如,打印为 。MANIFEST.MF``Implementation-Version: 1.0 |
${application.formatted-version} | 应用程序的版本号(在 中声明和格式化为显示)(用括号括在一起,并用 前缀。例如 , .MANIFEST.MF v (v1.0) |
${spring-boot.version} | 您使用的Spring Boot启动版本。例如 , .2.1.17.BUILD-SNAPSHOT |
${spring-boot.formatted-version} | 您使用的Spring Boot启动版本,格式化为显示(用括号括开,并使用 前缀)。例如 ,(v2.1.17.BUILD-SNAPSHOT) |
${Ansi.NAME} (或 ,${AnsiColor.NAME}``${AnsiBackground.NAME}``${AnsiStyle.NAME} ) | ANSI 转义码的名称在哪里。有关详细信息,请参阅安思财产 来源。NAME |
${application.title} | 应用程序的标题,如 中声明的。例如,打印为 。MANIFEST.MF Implementation-Title: MyApp |
如果要以编程方式生成横幅,可以使用SpringApplication.setBanner(…)
该方法。使用接口 org.springframework.boot.Banner
并实现您自己的方法printBanner()
。
还可以使用 spring.main.banner-mode
属性来确定横幅是否必须打印在 console
、发送到配置的记录器log
或是否未生成off
。
打印的横幅以以下名称注册为SpringBean: springBootBanner
。
YAML 配置文件中如果要禁用应用程序中的横幅,通过设为off
或false
禁用,请务必添加引号,如下例所示:
spring:
main:
banner-mode: "off"
16.3 定制Spring Boot应用
如果默认值不适合您的口味,您可以改为创建本地实例并对其进行自定义。例如,要关闭横幅,可以编写:SpringApplication
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
传递给构造函数的参数是 Spring bean 的配置源。在大多数情况下,这些是对类的引用,但它们也可以是对 XML 的配置或应扫描的包的引用。SpringApplication
@Configuration
SpringApplication
也可以使用application.properties
文件配置 。有关详细信息*,请参阅第 24*章外部配置**。
有关配置选项的完整列表,请参阅Spring应用
Javadoc。
16.4 流畅的生成器 API
如果需要构建层次结构(具有父/子关系的多个上下文),或者希望使用"流畅"生成器 API,可以使用SpringApplicationBuilder
。
允许您将多个方法调用和 :SpringApplicationBuilder
包括parent
和child
方法链接在一起,以便创建层次结构,如下例所示
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
创建层次结构时有一些限制。例如,Web组件必须包含在子上下文中,并且父上下文和子上下文都使用相同的组件。有关完整详细信息,请参阅
Spring应用程序构建器 Javadoc。ApplicationContext
Environment
16.5 应用程序事件和侦听器
除了通常的 Spring 框架事件(如ContextRefreshedEvent)之外
, SpringApplication
还发送一些额外的应用程序事件。
某些事件实际上在创建之前触发,因此不能将侦听器注册为您可以使用的方法注册它们。
ApplicationContext
@Bean
SpringApplication.addListeners(…)
SpringApplicationBuilder.listeners(…)
如果希望自动注册这些侦听器,而不管应用程序的创建方式如何,都可以将文件添加到项目中,并使用该键引用侦听器,如下例所示:
META-INF/spring.factories
org.springframework.context.ApplicationListener
org.springframework.context.ApplicationListener=com.example.project.MyListener
应用程序事件按以下顺序发送,因为应用程序运行:
ApplicationStartingEvent
在运行开始时发送,但在任何处理之前发送,但侦听器和初始化器的注册除外。- 当
ApplicationEnvironmentPreparedEvent
要在上下文中使用的Environment
是已知的,但在创建上下文之前发送的。 ApplicationPreparedEvent
在刷新开始之前发送,但在加载 bean 定义之后发送。ApplicationStartedEvent
在刷新上下文后,但在调用任何应用程序和命令行运行程序之前,将发送 。ApplicationReadyEvent
调用任何应用程序和命令行运行程序后发送 。它指示应用程序已准备好为请求提供服务。- 如果在启动时存在异常,则
ApplicationFailedEvent
发送 。
您通常不需要使用应用程序事件,但了解它们的存在会很方便。在内部,Spring Boot启动使用事件来处理各种任务。
使用 Spring 框架的事件发布机制发送应用程序事件。此机制的一部分可确保在子上下文中发布给侦听器的事件也已发布到任何祖先上下文中的侦听器。因此,如果应用程序使用实例层次结构,侦听器可能会接收相同类型的应用程序事件的多个SpringApplication
实例。
若要允许侦听器区分其上下文的事件和后代上下文的事件,应请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现ApplicationContextAware
或(如果侦听器是 bean)通过使用@Autowired
注入上下文。
16.6 网络环境
SpringApplication
ApplicationContext
代表您创建正确类型的测试。用于确定WebApplicationType
的算法如下:
- 如果存在SpringMVC,则使用
AnnotationConfigServletWebServerApplicationContext
- 如果SpringMVC 不存在,并且存在SpringWebFlux,则使用
AnnotationConfigReactiveWebServerApplicationContext
- 否则,使用
AnnotationConfigApplicationContext
这意味着,如果您在同一应用程序中使用 SpringMVC 和 SpringWebFlux中的新 MVC,则默认情况下将使用 SpringMVC。您可以通过调用WebClient
.setWebApplicationType(WebApplicationType)
轻松地重写 。
也可以完全控制调用 ApplicationContext
.setApplicationContextClass(…)
中使用的类型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rlwRiRpF-1596695506170)(https://docs.spring.io/spring-boot/docs/2.1.17.BUILD-SNAPSHOT/reference/html/images/tip.png)] |
---|
在JUnit测试中使用时,通常需要调用它.SpringApplication .setWebApplicationType(WebApplicationType.NONE) |
16.7 访问应用程序参数
如果您需要访问被传递到应用程序的参数,您可以注入一个Bean
,接口提供对原始参数的解析以及和参数的访问,如下例所示:
import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
@Component
public class MyBean {
@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}
}
Spring Boot也向Spring注册了参数,这也允许您可以通过使用注释注入单个应用程序参数
@Value
16.8 使用应用程序运行程序或命令行启动程序
如果需要在启动后运行某些特定代码,您可以继承ApplicationRunner
或CommandLineRunner
接口,两个接口以同样的方式运行并且提供一个单例的run
方法,他只会在SpringApplication.run(…)
完成前被调用。
CommandLineRunner
接口规定通过一个String数组来访问程序参数,然而ApplicationRunner
使用ApplicationArguments
接口在discussed 之前
下面是一个实现CommandLineRunner
接口的示例
import org.springframework.boot.*;
import org.springframework.stereotype.*;
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
如果多个CommandLineRunner
或ApplicationRunner
被定义,必须必须按特定顺序调用,您还可以实现org.springframework.core.Ordered
接口或者使用org.springframework.core.annotation.Order
注解
16.9 退出程序
每一个SpringApplication
通过JVM注册一个关闭钩子以保证程序退出时可以优雅的关闭ApplicationContext
,所有标准的Spring生命周期回调
被调用。
另外,beans也可以实现org.springframework.boot.ExitCodeGenerator
接口,如果需要在SpringApplication.exit()
被调用时返回一个特殊的返回码。然后可以传递此退出代码给System.exit()
以作为状态代码返回,如下所示:
@SpringBootApplication
public class ExitCodeApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));
}
}
同时,ExitCodeGenerator
接口或许被异常实现,当遇到这样一个异常,Spring Boot由实现的getExitCode()方法提供的退出码。
16.10 管理功能
可以通过指定spring.application.admin
来为应用程序启用与管理相关的特性。启用属性,这将在MBeanServer
平台上公开SpringApplicationAdminMXBean
。您可以使用此特性远程管理Spring Boot应用程序。这个功能也可以用于任何服务包装器实现。
如果您想知道应用程序在哪个HTTP端口上运行,请获取具有
local.server.port
的属性。