Spring Boot 自动配置的实现

 更新时间:2018年08月10日 10:24:34   作者:David_jim  
这篇文章主要介绍了Spring Boot 自动配置的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

Spring Boot 自动配置

来看下 spring boot中自动配置的注解

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

  String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

  /**
   * Exclude specific auto-configuration classes such that they will never be applied.
   * @return the classes to exclude
   */
  Class<?>[] exclude() default {};

  /**
   * Exclude specific auto-configuration class names such that they will never be
   * applied.
   * @return the class names to exclude
   * @since 1.3.0
   */
  String[] excludeName() default {};

}
  1. exclude() 可以排除一些自动配置的内容
  2. excludeName 通过名称排除自动配置内容

再来看下, @EnableAutoConfiguration 是怎么处理自动配置的呢?

注意到@Import(EnableAutoConfigurationImportSelector.class)

public class EnableAutoConfigurationImportSelector
    extends AutoConfigurationImportSelector {

  @Override
  protected boolean isEnabled(AnnotationMetadata metadata) {
    if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
      return getEnvironment().getProperty(
          EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
          true);
    }
    return true;
  }
}

}

再来看下 AutoConfigurationImportSelector ,主要是 接口的 ImportSelector 的实现

@Override
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
      return NO_IMPORTS;
    }
    try {
      //1、 自动配置的元数据 spring-autocomfigure-metadata.properties
      // 自动配置的开启条件
      AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
          .loadMetadata(this.beanClassLoader);
      AnnotationAttributes attributes = getAttributes(annotationMetadata);
      // 获取设置的自动配置列表 spring.factories
      List<String> configurations = getCandidateConfigurations(annotationMetadata,
          attributes);
      configurations = removeDuplicates(configurations);
      configurations = sort(configurations, autoConfigurationMetadata);
      // 获取要排除的自动配置列表,可以通过 注解@EnableAutoConfiguration 的exclude和
       // 配置文件设置 spring.autoconfigure.exclude key的值
      Set<String> exclusions = getExclusions(annotationMetadata, attributes);
      checkExcludedClasses(configurations, exclusions);
      configurations.removeAll(exclusions);
       // 通过 spring-autocomfigure-metadata.properties ConditionOnClass 条件进行过滤
      configurations = filter(configurations, autoConfigurationMetadata);
      fireAutoConfigurationImportEvents(configurations, exclusions);
      return configurations.toArray(new String[configurations.size()]);
    }
    catch (IOException ex) {
      throw new IllegalStateException(ex);
    }
  }

看下 spring.factories 文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\

再看下 spring framework中 ConfigurationClassParser 的处理方式,会解析 @Import 里的接口 ImportSelector 返回的所有配置类,那是怎么配置的呢,如 JpaRepositoriesAutoConfiguration

@Configuration
@ConditionalOnBean(DataSource.class)
@ConditionalOnClass(JpaRepository.class)
@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class,
    JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
@Import(JpaRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
public class JpaRepositoriesAutoConfiguration {

}

从上面可以看到,有很多的@ConditionalOn**的注解,我们来看下 ConditionEvaluator这个 条件计算器,会去计算出当前这个配置类 是否要开启,而这些 @ConditionalOn** 是依赖于 @Conditional 这个注解,如  @ConditionalOnBean 最终是通过 Condition 接口来作条件选择

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

  /**
   * The class type of bean that should be checked. The condition matches when any of
   * the classes specified is contained in the {@link ApplicationContext}.
   * @return the class types of beans to check
   */
  Class<?>[] value() default {};

  /**
   * The class type names of bean that should be checked. The condition matches when any
   * of the classes specified is contained in the {@link ApplicationContext}.
   * @return the class type names of beans to check
   */
  String[] type() default {};

  /**
   * The annotation type decorating a bean that should be checked. The condition matches
   * when any of the annotations specified is defined on a bean in the
   * {@link ApplicationContext}.
   * @return the class-level annotation types to check
   */
  Class<? extends Annotation>[] annotation() default {};

  /**
   * The names of beans to check. The condition matches when any of the bean names
   * specified is contained in the {@link ApplicationContext}.
   * @return the name of beans to check
   */
  String[] name() default {};

  /**
   * Strategy to decide if the application context hierarchy (parent contexts) should be
   * considered.
   * @return the search strategy
   */
  SearchStrategy search() default SearchStrategy.ALL;

}

Spring boot 的autoconfigure 是囊括了所有可以和spring 整合的项目,但大部分情况下,并不是所以的项目都会启用,通过 Condition和@Conditional 来判断条件

  1. 判断classPath 是否存在指定的类  @ConditionalOnClass
  2. 判断 ApplicationContext 中是否存在指定的 Bean  @ConditionalOnBean
  3. 配置环境中是否存在特定的配置项  @ConditionalOnProperty
  4. 配置环境中指定的配置项是否存在指定的值

禁用配置

当前 也是可以禁用某些我们不想要的默认配置,如上面加载时说到,会排除一些配置(exclude)

  1. 设置 @EnableAutoConfiguration 的exclude 配置
  2. 在配置文件增加 spring.autoconfigure.exclude 配置

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java的MyBatis框架中实现多表连接查询和查询结果分页

    Java的MyBatis框架中实现多表连接查询和查询结果分页

    这篇文章主要介绍了Java的MyBatis框架中实现多表连接查询和查询结果分页,借助MyBatis框架中带有的动态SQL查询功能可以比普通SQL查询做到更多,需要的朋友可以参考下
    2016-04-04
  • Java编程实现基于用户的协同过滤推荐算法代码示例

    Java编程实现基于用户的协同过滤推荐算法代码示例

    这篇文章主要介绍了Java编程实现基于用户的协同过滤推荐算法代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • 详解SpringBoot 调用外部接口的三种方式

    详解SpringBoot 调用外部接口的三种方式

    SpringBoot不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程,这篇文章主要介绍了SpringBoot 调用外部接口的三种方式,需要的朋友可以参考下
    2023-04-04
  • 简单通用JDBC辅助类封装(实例)

    简单通用JDBC辅助类封装(实例)

    下面小编就为大家带来一篇简单通用JDBC辅助类封装(实例)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • 详解Java单元测试之JUnit篇

    详解Java单元测试之JUnit篇

    这篇文章主要介绍了详解Java单元测试之JUnit篇,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • SparkStreaming整合Kafka过程详解

    SparkStreaming整合Kafka过程详解

    这篇文章主要介绍了SparkStreaming整合Kafka过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-01-01
  • Spring Boot集成springfox-swagger2构建restful API的方法教程

    Spring Boot集成springfox-swagger2构建restful API的方法教程

    这篇文章主要给大家介绍了关于Spring Boot集成springfox-swagger2构建restful API的相关资料,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-06-06
  • java代码之谜运算符篇

    java代码之谜运算符篇

    从最简单的运算符加号(+)说起,加号(+)是个二元运算符——也就是说,加号只把两个数联接起来,从来不把第三个或者更多的联接起来
    2012-11-11
  • 使用工具类-java精确到小数点后6位

    使用工具类-java精确到小数点后6位

    这篇文章主要介绍了使用工具类-java精确到小数点后6位,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Spring中@Autowired与@Resource的区别详析

    Spring中@Autowired与@Resource的区别详析

    @Autowired与@Resource都可以用来装配bean,都可以写在字段上,或写在setter方法上,下面这篇文章主要给大家介绍了关于Spring中@Autowired与@Resource区别的相关资料,需要的朋友可以参考下
    2021-10-10

最新评论