对于最新的稳定版本,请使用 Spring Boot 3.5.5! |
Spring Boot 应用程序
本节包括与 Spring Boot 应用程序直接相关的主题。
创建您自己的 FailureAnalyzer
FailureAnalyzer
是在启动时拦截异常并将其转换为人类可读的消息的好方法,并包装在FailureAnalysis
.
Spring Boot 为与应用程序上下文相关的异常、JSR-303 验证等提供了这样的分析器。
您也可以创建自己的。
AbstractFailureAnalyzer
是FailureAnalyzer
检查要处理的异常中是否存在指定的异常类型。
您可以从中扩展,以便您的实现只有在异常实际存在时才有机会处理异常。
如果出于某种原因无法处理异常,则返回null
让另一个实现有机会处理异常。
FailureAnalyzer
实现必须在META-INF/spring.factories
.
以下示例寄存器ProjectConstraintViolationFailureAnalyzer
:
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
如果您需要访问BeanFactory 或Environment ,将它们声明为FailureAnalyzer 实现。 |
自动配置故障排除
Spring Boot 自动配置会尽最大努力“做正确的事”,但有时事情会失败,而且很难说出原因。
有一个非常有用的ConditionEvaluationReport
在任何 Spring Boot 中可用ApplicationContext
.
如果启用DEBUG
日志记录输出。
如果您使用spring-boot-actuator
(参见执行器部分),还有一个conditions
以 JSON 格式呈现报表的端点。
使用该端点调试应用程序,并查看 Spring Boot 在运行时添加了哪些功能(以及哪些尚未添加)。
通过查看源代码和 API 文档可以回答更多问题。 阅读代码时,请记住以下经验法则:
-
查找名为
*AutoConfiguration
并阅读他们的来源。 特别注意@Conditional*
注释,以了解它们启用了哪些功能以及何时启用。 加--debug
到命令行或系统属性-Ddebug
在控制台上获取在应用中做出的所有自动配置决策的日志。 在启用了执行器的运行应用程序中,查看conditions
端点 (/actuator/conditions
或 JMX 等效产品)以获取相同的信息。 -
寻找符合以下条件的类
@ConfigurationProperties
(例如ServerProperties
),然后从那里读取可用的外部配置选项。 这@ConfigurationProperties
注释有一个name
充当外部属性前缀的属性。 因此ServerProperties
有prefix="server"
其配置属性为server.port
,server.address
,等。 在启用了执行器的运行应用程序中,查看configprops
端点。 -
寻找
bind
方法Binder
将配置值显式提取出Environment
以轻松的方式。 它通常与前缀一起使用。 -
查找
@Value
直接绑定到Environment
. -
查找
@ConditionalOnExpression
响应 SpEL 表达式打开和关闭特征的注释,通常使用从Environment
.
在启动之前自定义环境或 ApplicationContext
一个SpringApplication
有ApplicationListener
和ApplicationContextInitializer
用于将自定义应用于上下文或环境的实现。
Spring Boot 加载了许多此类自定义项以供内部使用META-INF/spring.factories
.
注册其他自定义项的方法不止一种:
-
以编程方式,每个应用程序通过调用
addListeners
和addInitializers
方法SpringApplication
在运行它之前。 -
以声明方式,对于所有应用程序,通过添加
META-INF/spring.factories
以及打包应用程序都用作库的 jar 文件。
这SpringApplication
发送一些特殊的ApplicationEvents
到侦听器(有些甚至在创建上下文之前),然后注册侦听器以获取ApplicationContext
也。
有关完整列表,请参阅“Spring Boot 功能”部分中的应用程序事件和侦听器。
也可以自定义Environment
在使用EnvironmentPostProcessor
.
每个实现都应在META-INF/spring.factories
,如以下示例所示:
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
该实现可以加载任意文件并将它们添加到Environment
.
例如,以下示例从类路径加载 YAML 配置文件:
-
Java
-
Kotlin
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);
}
}
}
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
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()) { "Resource $path does not 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 属性源,以便在任何通常的其他位置中定义的键优先。
自定义实现可以定义另一个顺序。 |
使用@PropertySource 在您的@SpringBootApplication 似乎是在Environment ,我们不推荐它。
此类属性源不会添加到Environment 直到刷新应用程序上下文。
这为时已晚,无法配置某些属性,例如logging.* 和spring.main.* 在刷新开始之前读取。 |
构建 ApplicationContext 层次结构(添加父上下文或根上下文)
您可以使用SpringApplicationBuilder
类创建父/子ApplicationContext
层次 结构。
有关更多信息,请参阅“Spring Boot 功能”部分中的 Fluent Builder API。
创建非 Web 应用程序
并非所有 Spring 应用程序都必须是 Web 应用程序(或 Web 服务)。
如果你想在main
方法,但也可以引导一个 Spring 应用程序来设置要使用的基础设施,你可以使用SpringApplication
Spring Boot 的功能。
一个SpringApplication
更改其ApplicationContext
类,具体取决于它是否认为它需要 Web 应用程序。
为了帮助它,您可以做的第一件事是将与服务器相关的依赖项(例如 servlet API)从类路径中剔除。
如果您无法做到这一点(例如,如果您从同一代码库运行两个应用程序),则可以显式调用setWebApplicationType(WebApplicationType.NONE)
在您的SpringApplication
实例或将applicationContextClass
属性(通过 Java API 或使用外部属性)。
要作为业务逻辑运行的应用程序代码可以实现为CommandLineRunner
并作为@Bean
定义。