跳到主要内容

Spring Boot 应用程序

DeepSeek V3 中英对照 Spring Boot Application

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

创建你自己的 FailureAnalyzer

FailureAnalyzer 是一种在启动时拦截异常并将其转换为人类可读消息的绝佳方式,该消息会被包装在 FailureAnalysis 中。Spring Boot 为与应用上下文相关的异常、JSR-303 验证等提供了这样的分析器。你也可以创建自己的分析器。

AbstractFailureAnalyzerFailureAnalyzer 的一个便捷扩展,它会检查异常中是否存在指定的异常类型以进行处理。你可以通过继承它,使得你的实现仅在异常实际存在时有机会处理该异常。如果由于某种原因你无法处理该异常,返回 null 以便其他实现有机会处理该异常。

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

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
properties
备注

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

自动配置故障排除

Spring Boot 的自动配置尽力“做正确的事情”,但有时候事情会失败,而很难确定原因。

在 Spring Boot 的 ApplicationContext 中,有一个非常实用的 ConditionEvaluationReport。如果你启用了 DEBUG 日志输出,就可以看到它。如果你使用了 spring-boot-actuator(参见 Actuator 部分),还会有一个 conditions 端点,它以 JSON 格式呈现报告。通过这个端点,你可以调试应用程序,并查看 Spring Boot 在运行时添加了哪些功能(以及哪些功能没有被添加)。

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

  • 查找名为 *AutoConfiguration 的类并阅读它们的源代码。特别注意 @Conditional* 注解,以了解它们启用了哪些功能以及在什么条件下启用。在命令行中添加 --debug 或系统属性 -Ddebug,以在控制台中获取应用程序中所有自动配置决策的日志。在启用了 Actuator 的运行应用程序中,查看 conditions 端点(/actuator/conditions 或等效的 JMX 端点)以获取相同的信息。

  • 查找带有 @ConfigurationProperties 注解的类(例如 ServerProperties),并从那里读取可用的外部配置选项。@ConfigurationProperties 注解有一个 name 属性,它作为外部属性的前缀。因此,ServerPropertiesprefix="server",其配置属性为 server.portserver.address 等。在启用了 Actuator 的运行应用程序中,查看 configprops 端点。

  • 查找在 Binder 上使用 bind 方法的情况,以宽松的方式从 Environment 中显式提取配置值。它通常与前缀一起使用。

  • 查找直接绑定到 Environment@Value 注解。

  • 查找 @ConditionalOnExpression 注解,这些注解根据 SpEL 表达式来开启或关闭功能,通常使用从 Environment 解析的占位符进行评估。

在启动前自定义环境或 ApplicationContext

一个 SpringApplication 包含 ApplicationListenerApplicationContextInitializer 的实现,用于对上下文或环境进行自定义。Spring Boot 从 META-INF/spring.factories 加载了许多这样的自定义实现以供内部使用。注册额外的自定义实现有多种方式:

  • 以编程方式,针对每个应用程序,在运行 SpringApplication 之前,调用其上的 addListenersaddInitializers 方法。

  • 以声明方式,针对所有应用程序,通过添加一个 META-INF/spring.factories 文件,并打包一个所有应用程序都作为库使用的 jar 文件。

SpringApplication 会向监听器发送一些特殊的 ApplicationEvents(有些事件甚至在上下文创建之前就会发送),然后还会为 ApplicationContext 发布的事件注册监听器。有关完整列表,请参见“Spring Boot 特性”部分中的 应用程序事件与监听器

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

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

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

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {

private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource path = new ClassPathResource("com/example/myapp/config.yml");
PropertySource<?> propertySource = loadYaml(path);
environment.getPropertySources().addLast(propertySource);
}

private PropertySource<?> loadYaml(Resource path) {
Assert.isTrue(path.exists(), () -> "Resource " + path + " does not exist");
try {
return this.loader.load("custom-resource", path).get(0);
}
catch (IOException ex) {
throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
}
}

}
java
提示

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

警告

虽然在你的 @SpringBootApplication 上使用 @PropertySource 可能看起来是一种在 Environment 中加载自定义资源的便捷方式,但我们不推荐这样做。这些属性源在应用程序上下文刷新之前不会被添加到 Environment 中。这对于配置某些属性(例如 logging.*spring.main.*)来说太晚了,因为这些属性在刷新开始之前就已经被读取了。

构建 ApplicationContext 层次结构(添加父级或根上下文)

你可以使用 SpringApplicationBuilder 类来创建父子 ApplicationContext 层级结构。更多信息请参阅“Spring Boot 特性”部分中的 Fluent Builder API

创建非 Web 应用程序

并非所有的 Spring 应用程序都必须是 Web 应用程序(或 Web 服务)。如果你想在 main 方法中执行一些代码,同时又希望启动一个 Spring 应用程序来设置所需的基础设施,你可以使用 Spring Boot 的 SpringApplication 功能。SpringApplication 会根据它是否认为需要一个 Web 应用程序来改变其 ApplicationContext 类。你可以做的第一件事是将与服务器相关的依赖(如 servlet API)从类路径中移除。如果你不能这样做(例如,如果你从同一个代码库运行两个应用程序),那么你可以在 SpringApplication 实例上显式调用 setWebApplicationType(WebApplicationType.NONE),或者设置 applicationContextClass 属性(通过 Java API 或外部属性)。你希望作为业务逻辑运行的应用程序代码可以实现为 CommandLineRunner,并作为 @Bean 定义放入上下文中。