On this page
23. SpringApplication
SpringApplication
类提供了一种方便的方式来引导将从main()
方法启动的 Spring 应用程序。在许多情况下,您可以只委托给静态SpringApplication.run
方法:
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}
当您的应用程序启动时,您应该看到类似于以下内容:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v1.5.9.RELEASE
2013-07-31 00:08:16.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)
2013-07-31 00:08:16.166 INFO 56603 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot[emailprotected]6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2014-03-04 13:09:54.912 INFO 41370 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-03-04 13:09:56.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running for 3.658)
默认情况下,将显示INFO
条记录消息,包括一些相关的启动详细信息,例如启动该应用程序的用户。
23.1 启动失败
如果您的应用程序无法启动,则已注册的FailureAnalyzers
有机会提供专用的错误消息和解决该问题的具体措施。例如,如果您在端口8080
上启动 Web 应用程序并且该端口已在使用中,则应该看到类似以下内容:
***************************
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.
Note
Spring Boot 提供了众多的FailureAnalyzer
实现,您可以很轻松地添加自己的。
如果没有故障分析器能够处理异常,您仍然可以显示完整的自动配置报告,以更好地了解出了什么问题。为此,您需要org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
启用调试属性或启用调试日志记录。
例如,如果您使用java -jar
运行应用程序,则可以启用debug
属性,如下所示:
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
23.2 自定义 banner
可以通过将banner.txt
文件添加到您的 Classpath 或将banner.location
设置为此类文件的位置来更改启动时打印的 banner。如果文件编码异常,则可以设置banner.charset
(默认为UTF-8
)。除了文本文件,您还可以将banner.gif
,banner.jpg
或banner.png
图像文件添加到 Classpath,或设置banner.image.location
属性。图像将转换为 ASCII 艺术作品并打印在任何 Literalsbanner 上方。
在banner.txt
文件中,您可以使用以下任意占位符:
表 23.1 标语变量
Variable | Description |
---|---|
${application.version} |
MANIFEST.MF 中声明的应用程序的版本号。例如Implementation-Version: 1.0 被打印为1.0 。 |
${application.formatted-version} |
以MANIFEST.MF 声明的格式显示的应用程序版本号(用括号括起来并以v 开头)。例如(v1.0) 。 |
${spring-boot.version} |
您正在使用的 Spring Boot 版本。例如1.5.9.RELEASE 。 |
${spring-boot.formatted-version} |
您正在使用的 Spring Boot 版本经过格式化以用于显示(用方括号括起来,并以v 作为前缀)。例如(v1.5.9.RELEASE) 。 |
${Ansi.NAME} (或${AnsiColor.NAME} ,${AnsiBackground.NAME} ,${AnsiStyle.NAME} ) |
其中NAME 是 ANSI 转义代码的名称。有关详情,请参见AnsiPropertySource。 |
${application.title} |
MANIFEST.MF 中声明的应用程序标题。例如Implementation-Title: MyApp 被打印为MyApp 。 |
Tip
如果要以编程方式生成 banner,则可以使用SpringApplication.setBanner(…)
方法。使用org.springframework.boot.Banner
接口并实现自己的printBanner()
方法。
您还可以使用spring.main.banner-mode
属性来确定是否必须使用配置的 Logger(log
)将 banner 打印在System.out
(console
)上或根本不打印(off
)。
打印的 banner 将被注册为名称为springBootBanner
的单例 bean。
Note
YAML 将off
Map 到false
,因此,如果要在应用程序中禁用 banner,请确保添加引号。
spring:
main:
banner-mode: "off"
23.3 自定义 SpringApplication
如果您不喜欢SpringApplication
默认值,则可以创建一个本地实例并对其进行自定义。例如,要关闭 banner,您可以编写:
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
Note
传递给SpringApplication
的构造函数参数是 spring bean 的配置源。在大多数情况下,它们将是对@Configuration
类的引用,但它们也可能是对 XML 配置或应扫描的程序包的引用。
也可以使用application.properties
文件配置SpringApplication
。有关详细信息,请参见* 第 24 章,外部化配置 *。
有关配置选项的完整列表,请参见SpringApplication Javadoc。
23.4 Fluent Builder API
如果您需要构建ApplicationContext
层次结构(具有父/子关系的多个上下文),或者只想使用“Fluent 的”构建器 API,则可以使用SpringApplicationBuilder
。
SpringApplicationBuilder
允许您将多个方法调用链接在一起,并包括parent
和child
方法,这些方法允许您创建层次结构。
For example:
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
Note
构建ApplicationContext
阶层时有一些限制,例如 Web 组件 必须 包含在子上下文中,并且相同的Environment
将用于父上下文和子上下文。有关详细信息,请参见SpringApplicationBuilder Javadoc。
23.5 应用程序事件和侦听器
除了通常的 Spring Framework 事件(例如ContextRefreshedEvent)之外,SpringApplication
还发送一些其他应用程序事件。
Note
有些事件实际上是在创建ApplicationContext
之前触发的,因此您不能将这些事件注册为@Bean
。您可以通过SpringApplication.addListeners(…)
或SpringApplicationBuilder.listeners(…)
方法注册它们。
如果您希望不管应用程序的创建方式如何自动注册那些侦听器,则可以将META-INF/spring.factories
文件添加到项目中,并使用org.springframework.context.ApplicationListener
键引用您的侦听器。
org.springframework.context.ApplicationListener=com.example.project.MyListener
应用程序事件在您的应用程序运行时按以下 Sequences 发送:
ApplicationStartingEvent
在运行开始时发送,但在进行任何处理(注册侦听器和初始化程序除外)之前都将发送。当知道要在上下文中使用的
Environment
时,但在创建上下文之前,将发送ApplicationEnvironmentPreparedEvent
。刚开始刷新之前但在加载 bean 定义之后发送
ApplicationPreparedEvent
。刷新后发送
ApplicationReadyEvent
,并且已处理所有相关的回调,以指示应用程序已准备好处理请求。如果启动时出现异常,则会发送
ApplicationFailedEvent
。
Tip
您通常不需要使用应用程序事件,但是知道它们的存在会很方便。在内部,Spring Boot 使用事件来处理各种任务。
应用程序事件是使用 Spring Framework 的事件发布机制发送的。该机制的一部分确保了在子上下文中发布给侦听器的事件也将在任何祖先上下文中发布给侦听器。结果,如果您的应用程序使用SpringApplication
实例的层次结构,则侦听器可能会收到同一类型的应用程序事件的多个实例。
为了使您的侦听器能够区分其上下文的事件和后代上下文的事件,它应请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现ApplicationContextAware
来注入上下文,或者,如果侦听器是 bean,则可以使用@Autowired
来注入上下文。
23.6 网络环境
SpringApplication
会代表您尝试创建正确的ApplicationContext
类型。默认情况下,将使用AnnotationConfigApplicationContext
或AnnotationConfigEmbeddedWebApplicationContext
,具体取决于您是否在开发 Web 应用程序。
用于确定“网络环境”的算法非常简单(基于几个类的存在)。如果您需要覆盖默认值,则可以使用setWebEnvironment(boolean webEnvironment)
。
也可以完全控制将通过调用setApplicationContextClass(…)
使用的ApplicationContext
类型。
Tip
在 JUnit 测试中使用SpringApplication
时,通常希望调用setWebEnvironment(false)
。
23.7 访问应用程序参数
如果您需要访问传递给SpringApplication.run(…)
的应用程序参数,则可以注入org.springframework.boot.ApplicationArguments
bean。 ApplicationArguments
接口提供对原始String[]
参数以及已解析的option
和non-option
参数的访问:
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"]
}
}
Tip
Spring Boot 还将在 Spring Environment
中注册一个CommandLinePropertySource
。这还允许您使用@Value
Comments 注入单个应用程序参数。
23.8 使用 ApplicationRunner 或 CommandLineRunner
如果在SpringApplication
启动后需要运行一些特定的代码,则可以实现ApplicationRunner
或CommandLineRunner
接口。两个接口以相同的方式工作,并提供一个run
方法,该方法将在SpringApplication.run(…)
完成之前被调用。
CommandLineRunner
接口提供对应用程序参数的访问,作为简单的字符串数组,而ApplicationRunner
接口则使用上面讨论的ApplicationArguments
接口。
import org.springframework.boot.*
import org.springframework.stereotype.*
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
如果定义了几个必须按特定 Sequences 调用的CommandLineRunner
或ApplicationRunner
bean,则可以另外实现org.springframework.core.Ordered
接口或使用org.springframework.core.annotation.Order
注解。
23.9 申请退出
每个SpringApplication
都会向 JVM 注册一个关闭钩子,以确保ApplicationContext
在退出时正常关闭。可以使用所有标准的 Spring 生命周期回调(例如DisposableBean
接口或@PreDestroy
注解)。
另外,如果 bean 希望在调用SpringApplication.exit()
时返回特定的退出代码,则可以实现org.springframework.boot.ExitCodeGenerator
接口。然后可以将此退出代码传递给System.exit()
,以将其作为状态代码返回。
@SpringBootApplication
public class ExitCodeApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return new ExitCodeGenerator() {
@Override
public int getExitCode() {
return 42;
}
};
}
public static void main(String[] args) {
System.exit(SpringApplication
.exit(SpringApplication.run(ExitCodeApplication.class, args)));
}
}
此外,ExitCodeGenerator
接口可能会通过异常实现。遇到此类异常时,Spring Boot 将返回已实现的getExitCode()
方法提供的退出代码。
23.10Management 员功能
通过指定spring.application.admin.enabled
属性,可以为应用程序启用与 Management 员相关的功能。这将在平台MBeanServer
上公开SpringApplicationAdminMXBean。您可以使用此功能来远程 ManagementSpring Boot 应用程序。这对于任何服务包装器实现也可能有用。
Tip
如果您想知道应用程序在哪个 HTTP 端口上运行,请使用键local.server.port
获取该属性。
Note
启用此功能时要小心,因为 MBean 公开了一种关闭应用程序的方法。