- 1 Spring Boot文档
- 1.1 关于这篇文档
- 1.2 获取帮助
- 1.3 第一步
- 1.4 使用Spring Boot
- 1.5 了解Spring Boot功能
- 1.6 转向生产
- 1.7 深入问题
- 2 入门
- 2.1 Spring Boot介绍
- 2.2 系统要求
- 2.3 安装Spring Boot
- 2.4 开发您的第一个Spring Boot应用程序
- 2.5 接下来要阅读的内容
- 3 使用Spring Boot
- 3.1 构建系统
- 3.1.1 依赖管理
- 3.2 结构化您的代码
- 3.3 配置类
- 3.4 自动配置
- 3.5 Spring Beans和依赖注入
- 3.6 使用@SpringBootApplication注解
- 3.7 运行您的应用程序
- 3.8 开发者工具
- 3.9 打包用于生产中的应用
- 3.10 接下来要阅读的内容
- 4 Spring Boot功能
- 4.1 SpringApplication
- 4.2 外部配置
- 4.3 Profiles
- 4.4 日志
- 4.5 国际化
- 4.6 JSON
- 4.7 开发Web应用程序
- 4.8 安全
- 4.9 使用SQL数据库
- 4.10 使用NoSQL技术
- 4.11 缓存
- 4.12 消息
- 4.13 使用RestTemplate调用REST服务
- 4.14 使用WebClient调用REST服务
- 4.15 校验
- 4.16 发送邮件
- 4.17 使用JTA的分布式事务
- 4.18 Hazelcast
- 4.19 Quartz Scheduler
- 4.20 任务执行和调度
- 4.21 Spring Integration
- 4.22 Spring Session
- 4.23 JMX的监控和管理
- 4.23 测试
- 4.25 WebSockets
- 4.26 Web Service
- 4.27 创建自己的自动配置
- 4.28 Kotlin支持
- 4.29 接下来要阅读的内容
- 5 Spring Boot Actuator: 生产就绪功能
- 5.1 启用生产就绪功能
- 5.2 Endpoints
- 5.3 通过HTTP进行监控和管理
- 5.4 JMX的监控和管理
- 5.5 Loggers
- 5.6 Metrics
- 5.7 审计
- 5.8 HTTP跟踪
- 5.9 进程监控
- 5.10 Cloud Foundry支持
- 5.11 接下来要阅读的内容
- 6 部署Spring Boot应用程序
- 6.1 部署到Cloud
- 6.2 安装Spring Boot应用程序
- 6.3 接下来要阅读的内容
- 7 Spring Boot CLI
- 7.1 安装CLI
- 7.2 使用CLI
- 7.3 使用Groovy Bean DSL开发应用程序
- 7.4 使用settings.xml配置CLI
- 7.5 接下来要阅读的内容
- 8 构建工具插件
- 8.1 Spring Boot Maven插件
- 8.2 Spring Boot Gradle插件
- 8.3 Spring Boot AntLib模块
- 8.4 支持其他构建系统
- 8.5 接下来要阅读的内容
- 9 ‘How-to’ 指南
- 9.1 Spring Boot应用
- 9.2 属性和配置
- 9.3 嵌入式Web服务器
- 9.4 Spring MVC
4.27 创建自己的自动配置
如果您在开发共享库的公司工作,或者您在开源或商业库中工作,则可能需要开发自己的自动配置。 自动配置类可以捆绑在外部jar中,仍然可以通过Spring Boot获取。
自动配置可以与“启动器”相关联,该“启动器”提供自动配置代码以及您将使用它的典型库。 我们首先介绍了构建自己的自动配置需要了解的内容,然后我们将继续介绍创建自定义启动器所需的典型步骤。
可以使用演示项目来展示如何逐步创建启动器。
4.27.1 了解自动配置的Bean
在幕后,使用标准的@Configuration类实现自动配置。 额外的@Conditional注释用于约束何时应用自动配置。 通常,自动配置类使用@ConditionalOnClass和@ConditionalOnMissingBean注释。 这可确保仅在找到相关类时以及未声明自己的@Configuration时才应用自动配置。
您可以浏览spring-boot-autoconfigure的源代码,以查看Spring提供的@Configuration类(请参阅META-INF/spring.factories文件)
4.27.2 匹配自动配置候选人
Spring Boot会检查已发布jar中是否存在META-INF/spring.factories文件。 该文件应列出EnableAutoConfiguration键下的配置类,如以下示例所示:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
必须以这种方式加载自动配置。 确保它们在特定的包空间中定义,并且它们永远不是组件扫描的目标。 此外,自动配置类不应启用组件扫描以查找其他组件。 应该使用特定的
@Import
代替。
如果需要按特定顺序应用配置,则可以使用@AutoConfigureAfter或@AutoConfigureBefore注释。 例如,如果您提供特定于Web的配置,则可能需要在WebMvcAutoConfiguration之后应用您的类。
如果您想排序某些不应该彼此直接了解的自动配置,您也可以使用@AutoConfigureOrder。 该注释与常规@Order注释具有相同的语义,但为自动配置类提供了专用顺序。
4.27.3 条件注解
您几乎总是希望在自动配置类中包含一个或多个@Conditional注释。 @ConditionalOnMissingBean注释是一个常见示例,用于允许开发人员如果对您的默认值不满意,则覆盖自动配置。
Spring Boot包含许多@Conditional注释,您可以通过注释@Configuration类或单独的@Bean方法在您自己的代码中重用它们。 这些注释包括:
- Class条件
- Bean条件
- Property条件
- Resource条件
- Web Application条件
- SpEL表达式条件
4.27.3.1 Class条件
@ConditionalOnClass和@ConditionalOnMissingClass注释允许根据特定类的存在与否来包含@Configuration类。 由于使用ASM解析注释元数据这一事实,您可以使用value属性来引用真实类,即使该类实际上可能不会出现在正在运行的应用程序类路径中。 如果您希望使用String值指定类名,也可以使用name属性。
这种机制不适用于@Bean方法,在这种方法中,返回类型通常是条件的目标:在应用该方法的条件之前,JVM将加载类和可能处理的方法引用,如果类不存在,这些引用将失败。
要处理这种情况,可以使用单独的@Configuration类来隔离条件,如以下示例所示:
@Configuration
// Some conditions
public class MyAutoConfiguration {
// Auto-configured beans
@Configuration
@ConditionalOnClass(EmbeddedAcmeService.class)
static class EmbeddedConfiguration {
@Bean
@ConditionalOnMissingBean
public EmbeddedAcmeService embeddedAcmeService() { ... }
}
}
如果使用@ConditionalOnClass或@ConditionalOnMissingClass作为元注释的一部分来组成自己的组合注释,则必须使用name作为引用类,在这种情况下不处理。
4.27.3.2 Bean条件
@ConditionalOnBean和@ConditionalOnMissingBean注释允许根据特定bean的存在与否包含bean。可以使用value属性按类型指定bean或按名称指定bean。Search属性允许您限制在搜索bean时应该考虑的ApplicationContext层次结构。
放置在@Bean方法上时,目标类型默认为方法的返回类型,如以下示例所示:
@Configuration
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService() { ... }
}
在前面的示例中,如果ApplicationContext中不包含MyService类型的bean,则将创建myService bean。
您需要非常小心添加bean定义的顺序,因为这些条件是根据到目前为止已处理的内容进行评估的。 因此,我们建议在自动配置类上仅使用@ConditionalOnBean和@ConditionalOnMissingBean注释(因为这些注释保证在添加任何用户定义的bean定义后加载)。
@ConditionalOnBean和@ConditionalOnMissingBean不会阻止创建@Configuration类。 在类级别使用这些条件并使用注释标记每个包含@Bean方法的唯一区别是,如果条件不匹配,前者会阻止将@Configuration类注册为bean。
4.27.3.3 Property条件
@ConditionalOnProperty注释允许基于Spring Environment属性包含配置。 使用prefix和name属性指定应检查的属性。 默认情况下,匹配存在且不等于false的任何属性。 您还可以使用havingValue和matchIfMissing属性创建更高级的检查。
4.27.3.4 Resource条件
@ConditionalOnResource注释仅允许在存在特定资源时包含配置。 可以使用常用的Spring约定来指定资源,如以下示例所示:file:/home/user/test.dat。
4.27.3.5 Web Application条件
@ConditionalOnWebApplication和@ConditionalOnNotWebApplication注释允许包含配置,具体取决于应用程序是否为“Web应用程序”。 Web应用程序是使用Spring WebApplicationContext,定义会话范围或具有StandardServletEnvironment的任何应用程序。
4.26.3.6 SpEL表达式条件
@ConditionalOnExpression批注允许根据SpEL表达式的结果包含配置。
4.27.4 测试您的自动配置
自动配置可能受许多因素的影响:用户配置(@Bean定义和环境定制),条件评估(存在特定库)等。 具体而言,每个测试都应该创建一个定义良好的ApplicationContext,它表示这些自定义的组合。 ApplicationContextRunner提供了一种实现它的好方法。
ApplicationContextRunner通常被定义为测试类的一个字段,用于收集基本的通用配置。 以下示例确保始终调用UserServiceAutoConfiguration:
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(UserServiceAutoConfiguration.class));
如果必须定义多个自动配置,则无需按照与运行应用程序时完全相同的顺序调用它们的声明。
每个测试都可以使用运行器来表示特定的用例。 例如,下面的示例调用用户配置(UserConfiguration)并检查自动配置是否正确退回。 调用run提供了一个可以与Assert4J一起使用的回调上下文。
@Test
public void defaultServiceBacksOff() {
this.contextRunner.withUserConfiguration(UserConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(UserService.class);
assertThat(context.getBean(UserService.class)).isSameAs(
context.getBean(UserConfiguration.class).myUserService());
});
}
@Configuration
static class UserConfiguration {
@Bean
public UserService myUserService() {
return new UserService("mine");
}
}
也可以轻松自定义环境,如以下示例所示:
@Test
public void serviceNameCanBeConfigured() {
this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
assertThat(context).hasSingleBean(UserService.class);
assertThat(context.getBean(UserService.class).getName()).isEqualTo("test123");
});
}
启动器还可用于显示ConditionEvaluationReport。 报告可以在INFO或DEBUG级别打印。 以下示例显示如何使用ConditionEvaluationReportLoggingListener在自动配置测试中打印报表。
@Test
public void autoConfigTest {
ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener(
LogLevel.INFO);
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withInitializer(initializer).run((context) -> {
// Do something...
});
}
4.27.4.1 模拟Web上下文
如果需要测试仅在Servlet或Reactive Web应用程序上下文中运行的自动配置,请分别使用WebApplicationContextRunner或ReactiveWebApplicationContextRunner。
4.27.4.2 覆盖Classpath
还可以测试在运行时不存在特定类和/或包时发生的情况。 Spring Boot附带了一个可以由Runner轻松使用的FilteredClassLoader。 在以下示例中,我们声明如果UserService不存在,则会正确禁用自动配置:
@Test
public void serviceIsIgnoredIfLibraryIsNotPresent() {
this.contextRunner.withClassLoader(new FilteredClassLoader(UserService.class))
.run((context) -> assertThat(context).doesNotHaveBean("userService"));
}
4.27.5 创建您自己的Starter
库的完整Spring Boot启动程序可能包含以下组件:
- 自动配置模块,包含自动配置代码。
- 启动器模块,它提供对autoconfigure模块以及库的依赖关系以及通常有用的任何其他依赖关系。 简而言之,添加启动器应该提供开始使用该库所需的一切。
如果您不需要将这两个问题分开,则可以将自动配置代码和依赖关系管理组合在一个模块中。
4.27.5.1 命名
您应该确保为您的启动器提供适当的命名空间。 即使您使用其他Maven groupId,也不要使用spring-boot启动模块名称。 我们可能会为您将来自动配置的内容提供官方支持。
根据经验,您应该在启动器后命名组合模块。 例如,假设您正在为“acme”创建启动器,并且您将自动配置模块命名为acme-spring-boot-autoconfigure和starter acme-spring-boot-starter。 如果您只有一个组合两者的模块,请将其命名为acme-spring-boot-starter。
此外,如果您的启动器提供配置密钥,请为它们使用唯一的命名空间。 特别是,不要将您的密钥包含在Spring Boot使用的命名空间中(例如server, management, spring等)。 如果您使用相同的命名空间,我们将来可能会以破坏您的模块的方式修改这些命名空间。
确保触发元数据生成,以便为您的密钥提供IDE帮助。 您可能希望查看生成的元数据(META-INF/spring-configuration-metadata.json)以确保正确记录您的密钥。
4.27.5.2 自动配置模块
autoconfigure模块包含开始使用库所需的所有内容。 它还可以包含配置键定义(例如@ConfigurationProperties)和任何可用于进一步自定义组件初始化方式的回调接口。
您应该将库的依赖项标记为可选,以便您可以更轻松地在项目中包含autoconfigure模块。 如果以这种方式执行,则不提供库,默认情况下,Spring Boot会退出。
Spring Boot使用注释处理器来收集元数据文件(META-INF / spring-autoconfigure-metadata.properties)中自动配置的条件。 如果该文件存在,则用于热切过滤不匹配的自动配置,这将缩短启动时间。 建议在包含自动配置的模块中添加以下依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
使用Gradle 4.5及更早版本时,应在compileOnly配置中声明依赖项,如以下示例所示:
dependencies {
compileOnly "org.springframework.boot:spring-boot-autoconfigure-processor"
}
使用Gradle 4.6及更高版本时,应在annotationProcessor配置中声明依赖项,如以下示例所示:
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}
4.27.5.3 Starter模块
起动器真的是一个空jar。 它的唯一目的是提供必要的依赖项来使用库。 您可以将其视为对入门所需内容的一种看法。
不要对添加启动器的项目做出假设。 如果您自动配置的库通常需要其他启动器,请同时提及它们。 如果可选依赖项的数量很高,则提供一组适当的默认依赖项可能很难,因为您应该避免包含对典型库的使用不必要的依赖项。 换句话说,您不应该包含可选的依赖项。
无论哪种方式,您的启动器必须直接或间接引用核心Spring Boot启动器(spring-boot-starter)(即如果您的启动器依赖于另一个启动器,则无需添加它)。 如果只使用自定义启动器创建项目,则Spring Boot的核心功能将通过核心启动器的存在来实现。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论