Spring Boot Application

本节包括与 Spring Boot 应用程序直接相关的主题。

This section includes topics relating directly to Spring Boot applications.

Create Your Own FailureAnalyzer

FailureAnalyzer 是一种很好的方法,它可以在启动时拦截异常并将其转换为人类可读的信息,并将其包装在一个 FailureAnalysis 中。Spring Boot 为与应用程序上下文相关的异常、JSR-303 验证等提供了此类分析器。你还可以创建自己的。

FailureAnalyzer is a great way to intercept an exception on startup and turn it into a human-readable message, wrapped in a FailureAnalysis. Spring Boot provides such an analyzer for application-context-related exceptions, JSR-303 validations, and more. You can also create your own.

AbstractFailureAnalyzerFailureAnalyzer 的便捷扩展,其检查要处理的异常中是否有指定的异常类型。您可以从那里扩展,以便只有在实际存在异常时您的实现才有机会处理它。如果出于任何原因,您无法处理异常,请返回 null,以使其他实现有机会处理异常。

AbstractFailureAnalyzer is a convenient extension of FailureAnalyzer that checks the presence of a specified exception type in the exception to handle. You can extend from that so that your implementation gets a chance to handle the exception only when it is actually present. If, for whatever reason, you cannot handle the exception, return null to give another implementation a chance to handle the exception.

必须在 META-INF/spring.factories 中注册 FailureAnalyzer 实现。以下示例注册 ProjectConstraintViolationFailureAnalyzer

FailureAnalyzer implementations must be registered in META-INF/spring.factories. The following example registers ProjectConstraintViolationFailureAnalyzer:

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer

如果您需要访问 BeanFactoryEnvironment,请在 FailureAnalyzer 实现中将它们声明为构造器参数。

If you need access to the BeanFactory or the Environment, declare them as constructor arguments in your FailureAnalyzer implementation.

Troubleshoot Auto-configuration

Spring Boot 自动配置竭尽所能 “do the right thing”,但有时会失败,并且很难说出原因。

The Spring Boot auto-configuration tries its best to “do the right thing”, but sometimes things fail, and it can be hard to tell why.

任何 Spring Boot ApplicationContext 都提供了一个非常有用的 ConditionEvaluationReport。如果您启用 DEBUG 日志输出,则可以看到它。如果您使用 spring-boot-actuator(请参见 the Actuator chapter),那么还会有一个 conditions 端点,将报告呈 JSON 格式。使用该端点可以调试应用程序,并查看 Spring Boot 在运行时添加了哪些功能(以及哪些功能尚未添加)。

There is a really useful ConditionEvaluationReport available in any Spring Boot ApplicationContext. You can see it if you enable DEBUG logging output. If you use the spring-boot-actuator (see the Actuator chapter), there is also a conditions endpoint that renders the report in JSON. Use that endpoint to debug the application and see what features have been added (and which have not been added) by Spring Boot at runtime.

通过查看源代码和 Javadoc,可以回答更多问题。在阅读代码时,请记住以下经验规则:

Many more questions can be answered by looking at the source code and the Javadoc. When reading the code, remember the following rules of thumb:

  • Look for classes called AutoConfiguration and read their sources. Pay special attention to the @Conditional annotations to find out what features they enable and when. Add --debug to the command line or a System property -Ddebug to get a log on the console of all the auto-configuration decisions that were made in your app. In a running application with actuator enabled, look at the conditions endpoint (/actuator/conditions or the JMX equivalent) for the same information.

  • Look for classes that are @ConfigurationProperties (such as {code-spring-boot-autoconfigure-src}/web/ServerProperties.java[ServerProperties]) and read from there the available external configuration options. The @ConfigurationProperties annotation has a name attribute that acts as a prefix to external properties. Thus, ServerProperties has prefix="server" and its configuration properties are server.port, server.address, and others. In a running application with actuator enabled, look at the configprops endpoint.

  • Look for uses of the bind method on the Binder to pull configuration values explicitly out of the Environment in a relaxed manner. It is often used with a prefix.

  • Look for @Value annotations that bind directly to the Environment.

  • Look for @ConditionalOnExpression annotations that switch features on and off in response to SpEL expressions, normally evaluated with placeholders resolved from the Environment.

Customize the Environment or ApplicationContext Before It Starts

SpringApplication 具有 ApplicationListenersApplicationContextInitializers,用于将自定义应用到上下文或环境。Spring Boot 从 META-INF/spring.factories 中加载了许多此类自定义供内部使用。有不止一种方法可以注册额外的自定义:

A SpringApplication has ApplicationListeners and ApplicationContextInitializers that are used to apply customizations to the context or environment. Spring Boot loads a number of such customizations for use internally from META-INF/spring.factories. There is more than one way to register additional customizations:

  • Programmatically, per application, by calling the addListeners and addInitializers methods on SpringApplication before you run it.

  • Declaratively, for all applications, by adding a META-INF/spring.factories and packaging a jar file that the applications all use as a library.

SpringApplication 向侦听器发送一些特殊的 ApplicationEvents(有些甚至在创建上下文之前),然后还为 ApplicationContext 发布的事件注册侦听器。请参阅“Spring Boot 功能”部分中的 “Application Events and Listeners” 以获取完整列表。

The SpringApplication sends some special ApplicationEvents to the listeners (some even before the context is created) and then registers the listeners for events published by the ApplicationContext as well. See “Application Events and Listeners” in the '`Spring Boot features’ section for a complete list.

还可以使用 EnvironmentPostProcessor 在刷新应用程序上下文之前自定义 Environment。应在 META-INF/spring.factories 中注册每个实现,如下例所示:

It is also possible to customize the Environment before the application context is refreshed by using EnvironmentPostProcessor. Each implementation should be registered in META-INF/spring.factories, as shown in the following example:

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

该实现可以加载任意文件并将其添加到 Environment。例如,以下示例从类路径中加载 YAML 配置文件:

The implementation can load arbitrary files and add them to the Environment. For instance, the following example loads a YAML configuration file from the classpath:

Environment 已经准备好了 Spring Boot 默认加载的所有常用属性源。因此,可以从环境中获取文件的位置。前面的示例在列表结尾添加了 custom-resource 属性源,以便优先使用在任何其他常用位置定义的键。自定义实现可以定义另一个顺序。

The Environment has already been prepared with all the usual property sources that Spring Boot loads by default. It is therefore possible to get the location of the file from the environment. The preceding example adds the custom-resource property source at the end of the list so that a key defined in any of the usual other locations takes precedence. A custom implementation may define another order.

虽然在 @SpringBootApplication 上使用 @PropertySource 看似是在 Environment 中加载自定义资源的一种便捷方式,但我们不建议这样做。在应用程序上下文正在刷新之前,这些属性源不会被添加到 Environment 中。这对于在刷新开始前会读取的特定属性(比如 logging. and spring.main.)来说,配置较迟。

While using @PropertySource on your @SpringBootApplication may seem to be a convenient way to load a custom resource in the Environment, we do not recommend it. Such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging. and spring.main. which are read before refresh begins.

Build an ApplicationContext Hierarchy (Adding a Parent or Root Context)

您可以使用 ApplicationBuilder 类来创建父/子 ApplicationContext 层次结构。有关更多信息,请参阅“Spring Boot 特性”部分中的 “Fluent Builder API”。

You can use the ApplicationBuilder class to create parent/child ApplicationContext hierarchies. See “Fluent Builder API” in the '`Spring Boot features’ section for more information.

Create a Non-web Application

并非所有 Spring 应用程序都必须是 Web 应用程序(或 Web 服务)。如果您想在一个 main 方法中执行一些代码,但也想引导 Spring 应用程序以设置基础设施,可以使用 Spring Boot 的 SpringApplication 特性。SpringApplication 更改了其 ApplicationContext 类,具体取决于它是否认为需要 Web 应用程序。您可以采取的第一项措施是帮助它不使用类路径上的服务器相关依赖项(比如 Servlet API)。如果您无法这样做(例如,您从相同的代码库运行两个应用程序),那么您可以显式在您的 SpringApplication 实例上调用 setWebApplicationType(WebApplicationType.NONE),或设置 applicationContextClass 属性(通过 Java API 或使用外部属性)。您希望作为业务逻辑运行的应用程序代码可以实现为 CommandLineRunner,并作为 @Bean 定义放入上下文。

Not all Spring applications have to be web applications (or web services). If you want to execute some code in a main method but also bootstrap a Spring application to set up the infrastructure to use, you can use the SpringApplication features of Spring Boot. A SpringApplication changes its ApplicationContext class, depending on whether it thinks it needs a web application or not. The first thing you can do to help it is to leave server-related dependencies (such as the servlet API) off the classpath. If you cannot do that (for example, you run two applications from the same code base) then you can explicitly call setWebApplicationType(WebApplicationType.NONE) on your SpringApplication instance or set the applicationContextClass property (through the Java API or with external properties). Application code that you want to run as your business logic can be implemented as a CommandLineRunner and dropped into the context as a @Bean definition.