参考:https://docs.spring.io/spring-boot/docs/1.5.17.RELEASE/reference/htmlsingle/#boot-features-developing-auto-configuration
如果公司是开发共享库的,或者在开源社区或商业库中工作,则可能需要开发自己的自动配置。自动配置类可以捆绑在外部jar中,仍然可以通过Spring Boot获取。自动配置可以与“starter”相关联,该“starter”提供自动配置代码以及将使用库。
官方自动配置的demo:https://github.com/snicoll-demos/spring-boot-master-auto-configuration
1. 理解自动配置的bean
使用标准的@Configuration类实现自动配置, 额外的@Conditional注解用于约束何时应用自动配置。 通常,自动配置类使用@ConditionalOnClass和@ConditionalOnMissingBean注解。 这可确保自动配置仅在找到相关类时以及未声明自己的@Configuration时应用。
可以浏览spring-boot-autoconfigure源码查看@Configuration类。(META-INF/spring.factories)
2. 找到自动配置候选项
Spring Boot会检查已发布jar中是否存在META-INF/spring.factories文件。 该文件应列出可以为EnableAutoConfiguration的配置类。如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
如果需要按特定顺序应用配置,则可以使用@AutoConfigureAfter或@AutoConfigureBefore注解。 例如,如果需要提供特定于Web的配置,则可能需要在WebMvcAutoConfiguration之后应用自定义的类。
如果想为某些不应该彼此直接了解的自动配置排序,也可以使用@AutoConfigureOrder。 该注解与常规@Order注解具有相同的语义,但为自动配置类提供了专用顺序。
注:必须以这种方式加载自动配置。 确保它们在特定的包空间中定义,并且它们永远不是组件扫描的目标。
3. 条件注解
几乎总是希望在自动配置类中包含一个或多个@Conditional注解。 @ConditionalOnMissingBean是一个常见示例,用于允许开发人员在他们对默认值不满意时“覆盖”自动配置。
Spring Boot包含许多@Conditional注解,可以通过注释@Configuration类或单独的@Bean方法在自己的代码中重用它们。
3.1 类条件
@ConditionalOnClass和@ConditionalOnMissingClass注解许根据特定类的存在与否来包含配置。由于使用ASM解析注释元数据,实际上可以使用value属性来引用真实类,即使该类实际上可能不会出现在正在运行的应用程序classpath中。 如果希望使用String值指定类名,也可以使用name属性。
注:如果使用@ConditionalOnClass或@ConditionalOnMissingClass作为元注解的一部分来组成自己的组合注解,则必须使用name作为引用类,否则配置不会被处理。
3.2 ben条件
@ConditionalOnBean和@ConditionalOnMissingBean注解允许根据特定bean的存在与否来包含bean。 可以使用value属性按类型指定bean,或使用name来按名称指定bean。 search属性允许限制在搜索bean时应考虑的ApplicationContext层次结构。
放置在@Bean方法上时,目标类型默认为方法的返回类型,例如:
@Configuration
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService() { ... }
}
上面例子中,如果ApplicationContext中不包含MyService类型的bean,则将创建myService bean。
注:
3.3 属性条件
@ConditionalOnProperty注解允许基于Spring Environment属性包含配置。 使用prefix和name属性指定应检查的属性。 默认情况下,将匹配存在且不等于false的任何属性。 还可以使用havingValue和matchIfMissing属性创建更高级的检查。
3.4 资源条件
@ConditionalOnResource注解仅允许在存在特定资源时包含配置。 可以使用常用的Spring约定来指定资源,例如file:/home/user/test.dat。
3.5 web应用程序条件
@ConditionalOnWebApplication和@ConditionalOnNotWebApplication注解允许包含配置,具体取决于应用程序是否为“Web应用程序”。 Web应用程序是使用Spring WebApplicationContext,定义会话范围或具有StandardServletEnvironment的任何应用程序。
3.6 SpringEL表达式条件
@ConditionalOnExpression注解允许根据SpEL表达式的结果包含配置。
4. 创建自定义的starter
完整Spring Boot启动程序可能包含以下组件:
注:如果不需要将这两个问题分开,则可以将自动配置代码和依赖关系管理组合在一个模块中。
4.1 命名
确保为starter提供一个合适的命名空间。即使使用的是其他的Maven groupId,也不要使用spring-boot启动模块名称。
这是一条经验法则。 假设正在为“acme”创建一个starter,将自动配置模块命名为acme-spring-boot-autoconfigure和starter acme-spring-boot-starter。 如果您只有一个模块将两者组合在一起,请使用acme-spring-boot-starter。
此外,如果starter提供配置密钥,请为它们使用适当的命名空间。 特别是,不要将密钥包含在Spring Boot使用的命名空间中(例如server,management,spring等)。 这些是官方的,可能会在未来改进/修改它们,这样可能会破坏我们自定义的的东西。
确保触发元数据生成,以便为密钥提供IDE帮助。 可能希望查看生成的元数据(META-INF/spring-configuration-metadata.json)以确保正确记录密钥。
4.2 自动配置模块
自动配置模块包含开始使用库所需的所有内容。 它还可以包含配置键定义(@ConfigurationProperties)和任何可用于进一步自定义组件初始化方式的回调接口。
注:应该将库的依赖项标记为可选,以便可以更轻松地在项目中包含autoconfigure模块。 如果这样做,将不提供库,默认情况下Spring Boot将退回。
Spring Boot使用注解处理器来收集元数据文件(META-INF/spring-autoconfigure-metadata.properties)中自动配置的条件。 如果该文件存在,则用于过滤不匹配的自动配置,这将缩短启动时间。 建议在包含自动配置的模块中添加以下依赖项:
org.springframework.boot
spring-boot-autoconfigure-processor
true
4.3 starter模块
starter是一个空jar。 它的唯一目的是为库提供必要的依赖关系。
不要对添加starter的项目做出假设。 如果自动配置的库通常需要其他启动器,请同时提及它们。 如果可选依赖项的数量很高,则提供一组适当的默认依赖项可能很难,因为应该避免为库的典型用法带来不必要的依赖项。
注:无论哪种方式,starter必须直接或间接引用核心Spring Boot启动器(spring-boot-starter)(即如果starter依赖于另一个启动器,则无需添加它)。 如果只使用自定义stater创建项目,则Spring Boot的核心功能将通过核心启动器的存在来实现。