SpringBoot(23) - 创建自定义stater(1)

参考: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。

注:

  • 需要非常小心添加bean定义的顺序,因为这些条件是根据到目前为止已处理的内容进行评估的。 因此,建议仅在自动配置类上使用@ConditionalOnBean和@ConditionalOnMissingBean注解(因为这些注解保证在添加任何用户定义的bean定义后加载)。
  • @ConditionalOnBean和@ConditionalOnMissingBean不会阻止创建@Configuration类。 在类级别使用这些条件和使用注解标记每个包含@Bean方法的唯一区别是,如果条件不匹配,前者会阻止将@Configuration类注册为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启动程序可能包含以下组件:

  • 自动配置模块包含自动配置代码
  • starter模块提供对自动配置模块以及库的依赖关系以及有用的任何其他依赖关系。 简而言之,添加starter应该就能够开始使用该库。

注:如果不需要将这两个问题分开,则可以将自动配置代码和依赖关系管理组合在一个模块中。

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的核心功能将通过核心启动器的存在来实现。

 

你可能感兴趣的:(springboot,springboot,条件注解,自定义starter)