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