此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Boot 4.0.4!spring-doc.cadn.net.cn

Spring Boot 应用程序

本节包含与 Spring Boot 应用程序直接相关的主题。spring-doc.cadn.net.cn

创建您自己的 FailureAnalyzer

FailureAnalyzer 是在启动时拦截异常并将其转换为包含在 FailureAnalysis 中的可读消息的好方法。 Spring Boot 为与应用上下文相关的异常、JSR-303 验证等提供了这样的分析器。 您也可以创建自己的分析器。spring-doc.cadn.net.cn

AbstractFailureAnalyzerFailureAnalyzer 的一个便捷扩展,它会检查待处理异常中是否存在指定类型的异常。 你可以继承该类,以便仅在异常实际存在时,让你的实现有机会处理该异常。 如果由于任何原因你无法处理该异常,请返回 null,以便让其他实现有机会处理该异常。spring-doc.cadn.net.cn

FailureAnalyzer 实现必须在 META-INF/spring.factories 中注册。 以下示例注册了 ProjectConstraintViolationFailureAnalyzerspring-doc.cadn.net.cn

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
如果您需要访问 BeanFactoryEnvironment,请在您的 FailureAnalyzer 实现中将它们声明为构造函数参数。

排查自动配置问题

Spring Boot 的自动配置会尽力“做正确的事”,但有时仍会失败,且难以查明原因。spring-doc.cadn.net.cn

有一个非常有用的ConditionEvaluationReport在任何Spring Boot ApplicationContext中可用。 如果您启用DEBUG日志输出,就可以看到它。 如果您使用spring-boot-actuator(请参阅Actuator部分),还有一个conditions端点,可以将报告以JSON格式呈现。 使用该端点来调试应用程序,并查看Spring Boot在运行时添加了哪些功能(以及未添加哪些功能)。spring-doc.cadn.net.cn

通过查看源代码和 API 文档,可以解答更多问题。 在阅读代码时,请牢记以下经验法则:spring-doc.cadn.net.cn

  • 查找名为 *AutoConfiguration 的类并阅读其源代码。 特别注意 @Conditional* 注解,以了解它们启用了哪些功能以及何时启用。 在命令行中添加 --debug 或设置系统属性 -Ddebug,以便在控制台中记录应用中做出的所有自动配置决策。 在启用了 Actuator 的运行应用程序中,查看 conditions 端点(/actuator/conditions 或其 JMX 等效项)以获取相同的信息。spring-doc.cadn.net.cn

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

  • 查找 bind 方法在 Binder 上的使用情况,以轻松的方式显式地从 Environment 中提取配置值。 它通常与前缀一起使用。spring-doc.cadn.net.cn

  • 查找直接绑定到 Environment@Value 个注解。spring-doc.cadn.net.cn

  • 查找 @ConditionalOnExpression 注解,这些注解根据 SpEL 表达式(通常使用从 Environment 解析的占位符进行求值)来启用或禁用功能。spring-doc.cadn.net.cn

在环境或 ApplicationContext 启动之前对其进行自定义

SpringApplication 拥有 ApplicationListenerApplicationContextInitializer 实现,用于对上下文或环境应用自定义配置。 Spring Boot 会从 META-INF/spring.factories 中加载许多此类自定义配置供内部使用。 注册额外自定义配置的方式不止一种:spring-doc.cadn.net.cn

  • 通过编程方式,针对每个应用程序,在运行之前调用 SpringApplication 上的 addListenersaddInitializers 方法。spring-doc.cadn.net.cn

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

SpringApplication 会向监听器发送一些特殊的 ApplicationEvents(有些甚至在上下文创建之前就会发送),然后还会注册用于监听由 ApplicationContext 发布的事件的监听器。 完整列表请参阅“Spring Boot 特性”部分中的 应用程序事件和监听器spring-doc.cadn.net.cn

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

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

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

import java.io.IOException;

import org.springframework.boot.EnvironmentPostProcessor;
import org.springframework.boot.SpringApplication;
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(), () -> "'path' [%s] must exist".formatted(path));
		try {
			return this.loader.load("custom-resource", path).get(0);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
		}
	}

}
import org.springframework.boot.EnvironmentPostProcessor
import org.springframework.boot.SpringApplication
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
import java.io.IOException

class MyEnvironmentPostProcessor : EnvironmentPostProcessor {

	private val loader = YamlPropertySourceLoader()

	override fun postProcessEnvironment(environment: ConfigurableEnvironment, application: SpringApplication) {
		val path: Resource = ClassPathResource("com/example/myapp/config.yml")
		val propertySource = loadYaml(path)
		environment.propertySources.addLast(propertySource)
	}

	private fun loadYaml(path: Resource): PropertySource<*> {
		Assert.isTrue(path.exists()) { "'path' [$path] must exist" }
		return try {
			loader.load("custom-resource", path)[0]
		} catch (ex: IOException) {
			throw IllegalStateException("Failed to load yaml configuration from $path", ex)
		}
	}

}
Environment 已经准备好了 Spring Boot 默认加载的所有常用属性源。 因此,可以从环境中获取文件的位置。 前面的示例将 custom-resource 属性源添加到列表的末尾,以便在其他任何常用位置定义的键具有优先权。 自定义实现可以定义另一种顺序。
在您的 @SpringBootApplication 上使用 @PropertySource 似乎是一种在 Environment 中加载自定义资源的便捷方式,但我们不建议这样做。 此类属性源直到应用程序上下文被刷新时才会被添加到 Environment。 这为时已晚,无法配置某些属性,例如 logging.*spring.main.*,因为它们会在刷新开始之前被读取。

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

您可以使用 SpringApplicationBuilder 类来创建父子 ApplicationContext 层次结构。 有关更多信息,请参阅“Spring Boot 特性”部分中的 Fluent Builder APIspring-doc.cadn.net.cn

创建非 Web 应用程序

并非所有的 Spring 应用程序都必须是 Web 应用程序(或 Web 服务)。 如果您希望在 main 方法中执行某些代码,同时引导 Spring 应用程序以设置要使用的基础设施,您可以使用 Spring Boot 的 SpringApplication 功能。 SpringApplication 会根据其判断是否需要 Web 应用程序来更改其 ApplicationContext 类。 您可以采取的首要措施是将与服务器相关的依赖项(例如 Servlet API)从类路径中移除。 如果无法这样做(例如,如果您从同一代码库运行两个应用程序),则可以在您的 SpringApplication 实例上显式调用 setWebApplicationType(WebApplicationType.NONE),或者设置 applicationContextClass 属性(通过 Java API 或使用外部属性)。 您希望作为业务逻辑运行的应用程序代码可以实现为 CommandLineRunner,并作为 @Bean 定义放入上下文中。spring-doc.cadn.net.cn