Spring Boot 自动配置

作者: David_jim | 来源:发表于2018-08-08 15:27 被阅读7次

    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 {};
    
    }
    
    • exclude() 可以排除一些自动配置的内容
    • 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 配置

    相关文章

      网友评论

        本文标题:Spring Boot 自动配置

        本文链接:https://www.haomeiwen.com/subject/iohxbftx.html