Spring Boot 教程

Spring Boot 自动配置简介

Spring Boot 自动配置是 Spring Boot 的一个非常重要、也是非常好用的特性。

Spring Boot 自动配置功能可以根据不同条件自动决定 Spring 配置中,那些 Bean 该创建,哪些 Bean 不该创建。举个例子:

  • 在 classpath 中是否存在 Spring 的 JdbcTemplate?如果在 classpath 中存在 JdbcTemplate 类,并且 DataSource 也存在,那么久自动配置一个 JdbcTemplate Bean。

  • 在 classpath 中是否存在 Thymeleaf 类?如果存在,则自动配置 Thymeleaf 的模板解析器、视图解析器、模板引擎等

那个这个是怎么实现的呢?原因就在于它利用了 Spring 的条件化配置,条件化配置允许配置存在于应用中。但是在满足某些特定条件前会忽略这些配置;只有满足某个条件时,配置才会有效。

要实现条件化配置我们要用到 @Conditional 注解(位于 org.springframework.context.annotation 包,注意:自 spring 4.0 开始才支持),源码如下:

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

   /**
    * All {@link Condition} classes that must {@linkplain Condition#matches match}
    * in order for the component to be registered.
    */
   Class<? extends Condition>[] value();

}

只有当所有在 @Conditional 注解中指定条件都匹配时,组件才有资格注册。@Conditional 注解的条件是可以在要注册 Bean 定义之前以编程方式确定的任何状态。

@Conditional 注解可以通过以下任何一种方式使用:

  • 作为直接或间接用 @Component 注解的任何类的类级别注释,包括 @Configuration 修饰的类;

  • 作为元注释,用于组合自定义注解;

  • 作为任何 @Bean 方法上的方法级注释;

如果 @Configuration 注解修饰的类上标记有 @Conditional 注解,则与该类关联的所有 @Bean 方法,@Import 注解和@ComponentScan 注解将受此条件限制。

注意:

@Conditional 注解不支持继承特性,不会考虑超类或重写方法中的任何条件。为了强制执行这些语义,@Conditional 本身未使用 @Inherited 注解声明;

此外,任何使用 @Conditional 进行元注释的自定义组合注解都不得包含 @Inherited 注解。

Spring Boot 在 @Conditional 注解的基础上提供了更多的便捷注解,见 org.springframework.boot.autoconfigure.condition 包,常见便捷注解如下:

  • ConditionalOnBean:@Conditional 仅在满足所有指定要求的bean已包含在 BeanFactory 中时才匹配。

  • ConditionalOnClass:@Conditional 仅当指定的类在类路径上时才匹配。

  • ConditionalOnCloudPlatform:当指定的云平台处于活动状态时,@Conditional 匹配。

  • ConditionalOnExpression:取决于 SpEL 表达式值的条件元素的配置注释。

  • ConditionalOnJava:根据应用程序运行的 JVM 版本进行匹配的 @Conditional。

  • ConditionalOnJndi:根据 JNDI InitialContext 的可用性和查找特定位置的能力进行匹配的 @Conditional。

  • ConditionalOnMissingBean:@Conditional 仅在BeanFactory中已不包含满足指定要求的bean时匹配。

  • ConditionalOnMissingClass:@Conditional 仅在指定的类不在类路径上时才匹配。

  • ConditionalOnNotWebApplication:@Conditional 仅在应用程序上下文不是Web应用程序上下文时才匹配。

  • ConditionalOnProperty:@Conditional 检查指定的属性是否具有特定值。

  • ConditionalOnResource:@Conditional 仅在指定资源位于类路径上时才匹配。

  • ConditionalOnSingleCandidate:@Conditional 仅在 BeanFactory 中已经包含指定类的 bean 并且可以确定单个候选对象时才匹配。

  • ConditionalOnWarDeployment:当应用程序为传统 WAR 部署时匹配的 @Conditional。

  • ConditionalOnWebApplication:当应用程序是Web应用程序时匹配的@Conditional。

我们在 Spring Cloud 源码中,随处可见 Spring Boot 自动配置的条件注解的身影,例如:

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
@ConditionalOnBlockingDiscoveryEnabled
public class EurekaDiscoveryClientConfiguration {

   @Bean
   @ConditionalOnMissingBean
   public EurekaDiscoveryClient discoveryClient(EurekaClient client, EurekaClientConfig clientConfig) {
      return new EurekaDiscoveryClient(client, clientConfig);
   }
   // ...
}

上面代码中的 @ConditionalOnClass、@ConditionalOnProperty、@ConditionalOnMissingBean 等注解的含义和详细用法将在后续章节进行详细介绍。

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号