|
对于最新的稳定版本,请使用 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 应用程序来设置要使用的基础设施,你可以使用SpringApplicationSpring Boot 的功能。
一个SpringApplication更改其ApplicationContext类,具体取决于它是否认为它需要 Web 应用程序。
为了帮助它,您可以做的第一件事是将与服务器相关的依赖项(例如 servlet API)从类路径中剔除。
如果您无法做到这一点(例如,如果您从同一代码库运行两个应用程序),则可以显式调用setWebApplicationType(WebApplicationType.NONE)在您的SpringApplication实例或将applicationContextClass属性(通过 Java API 或使用外部属性)。
要作为业务逻辑运行的应用程序代码可以实现为CommandLineRunner并作为@Bean定义。