Spring Boot核心原理-自动配置 以及@ConfigurationProperties 注解

      若是你所在的公司要开发一个共享的lib,或者若是你想要为开源世界作点贡献,你也许想要开发你本身的自定义的自动配置类以及你本身的starter pom。这些自动配置类虽然在一个单独的jar包中,但却依然可以被Spring Boot获取到。web

自动配置(Auto-configuration)其实就是一个starter。starter这个词是否是很熟悉,没错,就是Spring Boot中的那些看起来略屌的启动器。如今你能够本身编写一个本身的starter了。在一个starter里,你能够把一组dependency和标记有@Configuration的类放在这个starter里。spring

1.理解 auto-configured beans

自动配置使用标准的@Configuration类实现。 而后能够搭配@Conditional注解来规定在什么条件下这些配置会被使用和生效。 其中自动配置类最经常使用到的就是@ConditionalOnClass和@ConditionalOnMissingBean这两个注解。 express

这样的话,就能够保证在找到相关的类或Bean的时候的时候自动配置类才会生效。session

2.如何定位自动配置类

若是你在本身单独的jar包中编写了一个自动配置类,并且加上了@Configuration以及其它约束条件,这时候引入依赖的话,你的Configuration并不会生效。app

你还须要在你的starter项目中的resources文件夹下加上META-INF /spring.factories这样的目录和文件,Spring Boot会检查你发布的jar中是否存在META-INF / spring.factories文件。 在这个文件中你应该把你的配置类加入进来,像下面这样,在一个EnableAutoConfiguration key下。spring-boot

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration

若是你的配置类须要按照必定的顺序来逐个生效的话,你可使用@AutoConfigureAfter或@AutoConfigureBefore来实现。spa

好比,若是你搞了个web的一个自定义配置,那么你的这个配置的生效就要排在WebMvcAutoConfiguration的后面设计

蕾丝下面这样:code

 

@Configuration
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class HornetQAutoConfiguration {...

若是您想排序某些彼此不该该有什么直接关联的自动配置类的话,您还可使用@AutoconfigureOrder。 该注解与常规的@Order注解具备相同的语义,但为自动配置类提供了一个你想要的顺序。排序

/**
 * Auto-configuration为你定义了好几个注解可让你的自动配置类按照必定的顺序自动排列
* 具体就是经过AnnotationConfigApplicationContext#register(Class...)}来为你生成的

 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
public @interface AutoConfigureOrder {
    /**
     * 排序方式. 默认是Ordered#LOWEST_PRECEDENCE
     * @see Ordered#getOrder()
     * @return the order value
     */
    int value() default Ordered.LOWEST_PRECEDENCE;
}

这个Ordered也就是两种状况:

public interface Ordered {
    int HIGHEST_PRECEDENCE = -2147483648;//优先级最高
    int LOWEST_PRECEDENCE = 2147483647;//优先级最低
    int getOrder();
}

NOTE:自动配置类只能以这种方式加载。这样才能保证他们被限定在特定包中而且它们不会被其它的组件扫描到!

3. Condition注解

通常状况下,你都要给你的自动配置类加上一个或者更多的@Conditional注解。好比@ConditionalOnMissingBean就是一个比较常见的例子,当你容许开发人员去覆盖自动配置的时候,那么强烈建议你使用这个注解,这样的话,若是开发人员以为你的自动配置并不能知足需求,那么他能够自定义。

特别注意:@ConditionalOnMissingBean也只适合在自动配置类中使用。千万不要乱用。

Spring Boot自带了一些@Conditional注解,你能够在你的代码中重用,在标记了@Configuration的类或@Bean方法上。

3.1 Class conditions

@ConditionalOnClass和@ConditionalOnMissingClass注解其实就是当特定的类存在就生效,反之亦然。 因为这些注解上的元数据是使用ASM来解析,因此你能够经过name属性来引入一个类,这样也不在意这个类在没在你的classpath中。

@ConditionalOnClass(name ="de.MyService")

若是你使用value属性的话,若是所在类不存在的话,则会报错致使编译没法经过。

像下面这样:

@ConditionalOnClass({de.MyService.class})

3.2 Bean conditions

@ConditionalOnBean和@ConditionalOnMissingBean上面已经介绍过了。也能够经过name或value属性来指定bean。 还有一个search属性,经过该属性你能够指定搜索bean时所使用的ApplicationContext。


3.3 Property conditions


@ConditionalOnProperty注解容许配置包含基于Spring Environment的属性。 使用prefix和name属性指定应检查的属性。 默认状况下,任何存在且不等于false的属性都将匹配。 你还可使用havingValue和matchIfMissing属性进行更高级的过滤和检查。

@ConditionalOnProperty(prefix = "hornetq.embedded", value = "enabled", havingValue ="true", matchIfMissing = true)

static class EmbeddedServerConfiguration {

//相似这样,hrnetq.embedded.enabled=true,EmbeddedServerConfiguration的配置就生效了;

//若是你把havingValue修改成false,该配置仍是生效的,由于你加了matchIfMissing = true,若是你把

//matchIfMissing改成false,该配置就失效了。

3.4 Resource conditions

@ConditionalOnResource 同理,当某个资源文件存在时,则配置生效。 

资源可使用一般的Spring约定来指定,例如,file:/home/user/test.dat。

3.5 Web application conditions

同理@ConditionalOnWebApplication 和 @ConditionalOnNotWebApplication是用来判断应用是否是web应用:web application。

 

这里所说的Web应用程序是指任何使用了Spring WebApplicationContext,定义了session scope或者有标准servlet环境的任何应用程序。

3.6 SpEL expression conditions

@ConditionalOnExpression也是同样的。至于SpEL是个什么东东?这里不赘述了。

 

相似这样的用法:

@ConditionalOnExpression("'Hello World'.concat('!')")

源码:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnExpressionCondition.class)
public @interface ConditionalOnExpression {

    /**
     * 设置spring的表达式语言: SpEL expression。表达式应该返回true或false。默认是true
     * @return the SpEL expression
     */
    String value() default "true";

}

4 建立你本身的starter

一个完整的Spring Boot 的starter能够包含两个组件(注意:是“能够”包含):

  • autoconfigure 模块。 自动配置类代码。

  • starter 模块。 自动配置相关的依赖以及其它要启动starter所要提供能力的相关依赖,总之,要保证starter所提供的能力可以正常启动。

     

NOTE:若是你以为不必把这两个分开的话,你能够把两个模块合并成一个。

 

 

4.1 起名字

不说了。学会模仿。

4.2 Autoconfigure 模块

Autoconfigure模块包含有你的自动配置类以及和配置类相关联的类好比@ConfigurationProperties这些类以及任何未来要进一步自定义组件的回调接口等代码。

NOTE:注意把一些库的dependency标记为optional,以便您能够更轻松地在项目中包含自动配置模块。这也是你设计sdk的一些技巧。

4.3 Starter 模块

Starter模块就是一个空的jar。里边只有一个pom。而后提供启动所须要的依赖。

-----------分割线--------------

:你须要加入两个与自动配置相关的依赖:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-configuration-processor</artifactId>
   <optional>true</optional>
</dependency>

-----------我再分-----------

相关文章
相关标签/搜索