44. 创建自己的自动配置
如果您在开发共享库的公司中工作,或者在开源或商业库中工作,则可能需要开发自己的自动配置。自动配置类可以 Binding 在外部 jar 中,并且仍由 Spring Boot 拾取。
自动配置可以与“启动器”相关联,该“启动器”提供自动配置代码以及您将使用的典型库。我们将首先介绍构建自己的自动配置所需的知识,然后我们将 continue 讨论创建自定义启动器所需的典型步骤。
Tip
demo project可用来展示如何逐步创建 Starter 程序。
44.1 了解自动配置的 Bean
在后台,自动配置是通过标准的@Configuration
类实现的。其他@Conditional
Comments 用于约束何时应应用自动配置。通常,自动配置类使用@ConditionalOnClass
和@ConditionalOnMissingBean
Comments。这样可以确保自动配置仅在找到相关的类且未声明自己的@Configuration
时适用。
您可以浏览spring-boot-autoconfigure的源代码以查看我们提供的@Configuration
类(请参见META-INF/spring.factories文件)。
44.2 查找自动配置候选对象
Spring Boot 检查发布的 jar 中是否存在META-INF/spring.factories
文件。该文件应在EnableAutoConfiguration
键下列出您的配置类。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
如果需要按特定 Sequences 应用配置,则可以使用@AutoConfigureAfter或@AutoConfigureBefore注解。例如,如果您提供特定于 Web 的配置,则可能需要在WebMvcAutoConfiguration
之后应用您的类。
如果要 Order 某些彼此之间不具有直接了解的自动配置,则也可以使用@AutoConfigureOrder
。该 Comments 与常规@Order
Comments 具有相同的语义,但为自动配置类提供了专用 Sequences。
Note
自动配置必须以* only *的方式加载。确保在特定的程序包空间中定义它们,并且永远不要将它们作为组件扫描的目标。
44.3 条件 Comments
您几乎总是希望在自动配置类中包含一个或多个@Conditional
Comments。 @ConditionalOnMissingBean
是一个常见示例,用于使开发人员在对默认设置不满意的情况下“覆盖”自动配置。
Spring Boot 包含许多@Conditional
Comments,您可以通过 Comments@Configuration
类或单个@Bean
方法在自己的代码中重用。
44.3.1Class 条件
@ConditionalOnClass
和@ConditionalOnMissingClass
注解允许根据是否存在特定类来包含配置。由于 Comments 元数据是使用ASM进行解析的,因此您实际上可以使用value
属性来引用真实的类,即使该类实际上可能未出现在正在运行的应用程序 Classpath 上。如果您希望使用String
值指定类名,则也可以使用name
属性。
Tip
如果将@ConditionalOnClass
或@ConditionalOnMissingClass
作为元 Comments 的一部分来组成自己的组合 Comments,则必须使用name
,因为在这种情况下无法引用该类。
44.3.2 Bean 条件
@ConditionalOnBean
和@ConditionalOnMissingBean
Comments 允许根据是否存在特定 bean 来包含 bean。您可以使用value
属性按类型指定 bean,或使用name
按名称指定 bean。 search
属性允许您限制搜索 Bean 时应考虑的ApplicationContext
层次结构。
当放置在@Bean
方法上时,目标类型默认为该方法的返回类型,例如:
@Configuration
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService() { ... }
}
在上面的示例中,如果ApplicationContext
中没有包含类型MyService
的 bean,则将创建myService
bean。
Tip
您需要非常注意 Bean 定义的添加 Sequences,因为这些条件是根据到目前为止已处理的内容进行评估的。因此,我们建议仅在自动配置类上使用@ConditionalOnBean
和@ConditionalOnMissingBean
Comments(因为保证在添加任何用户定义的 Bean 定义后即可加载这些 Comments)。
Note
@ConditionalOnBean
和@ConditionalOnMissingBean
不会阻止@Configuration
类的创建。在类级别使用这些条件等效于用 Comments 标记每个@Bean
方法。
44.3.3Property 条件
@ConditionalOnProperty
Comments 允许基于 Spring Environment 属性包含配置。使用prefix
和name
属性来指定应检查的属性。默认情况下,将匹配存在且不等于false
的任何属性。您还可以使用havingValue
和matchIfMissing
属性创建更高级的检查。
44.3.4 资源条件
@ConditionalOnResource
Comments 仅在存在特定资源时才允许包含配置。可以使用通常的 Spring 约定来指定资源,例如file:/home/user/test.dat
。
44.3.5 Web 应用程序条件
@ConditionalOnWebApplication
和@ConditionalOnNotWebApplication
注解允许根据应用程序是否为“ Web 应用程序”来包含配置。 Web 应用程序是使用 Spring WebApplicationContext
,定义session
范围或具有StandardServletEnvironment
的任何应用程序。
44.3.6 SpEL 表达条件
@ConditionalOnExpression
注解允许基于SpEL expression的结果包括配置。
44.4 创建自己的 Starter
库的完整 Spring BootStarter 程序可能包含以下组件:
-
包含自动配置代码的
autoconfigure
模块。 -
starter
模块提供对自动配置模块以及库的依赖关系,以及通常有用的任何其他依赖关系。简而言之,添加启动程序应该足以开始使用该库。
Tip
如果不需要将这两个问题分开,则可以将自动配置代码和依赖性 Management 结合在一起。
44.4.1 Naming
请确保为您的 Starter 者提供适当的名称空间。即使您使用的是其他 Maven groupId,也不要以spring-boot
开头模块名称。我们可能会在将来为您自动配置的产品提供官方支持。
这是一个经验法则。假设您要为“ acme”创建启动器,将自动配置模块命名为acme-spring-boot-autoconfigure
,并将启动器命名为acme-spring-boot-starter
。如果只有一个模块将两者结合在一起,请使用acme-spring-boot-starter
。
此外,如果您的 Starter 者提供了配置密钥,请为其使用适当的命名空间。特别是,不要在 Spring Boot 使用的名称空间中包含您的密钥(例如server
,management
,spring
等)。这些是“我们的”,我们将来可能会以破坏您的事情的方式对其进行改进/修改。
确保触发元数据生成,以便您的按键也可以使用 IDE 协助。您可能需要查看生成的元数据(META-INF/spring-configuration-metadata.json
),以确保正确记录了您的密钥。
44.4.2 自动配置模块
自动配置模块包含开始使用该库所需的一切。它还可能包含配置键定义(@ConfigurationProperties
)和可用于进一步自定义组件初始化方式的任何回调接口。
Tip
您应该将对库的依赖关系标记为可选,以便可以更轻松地在项目中包括自动配置模块。如果这样做,将不会提供该库,并且默认情况下,Spring Boot 将关闭。
44.4.3Starter 模块
起动器确实是一个空Jar子。其唯一目的是提供必要的依赖关系以使用库。将其视为 Starter 必备的观点。
不要对添加了启动器的项目做任何假设。如果您要自动配置的库通常需要其他启动器,请同时提及它们。如果可选依赖项的数量很高,则提供一组适当的* default *依赖项可能会很困难,因为您应避免为库的典型用法带来不必要的依赖项。