Spring Boot 自動(dòng)配置

Spring Boot 自動(dòng)配置

來(lái)看下 spring boot中自動(dòng)配置的注解

@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() 可以排除一些自動(dòng)配置的內(nèi)容
  • excludeName 通過(guò)名稱排除自動(dòng)配置內(nèi)容

再來(lái)看下腿堤,@EnableAutoConfiguration 是怎么處理自動(dòng)配置的呢脆丁?

注意到@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;
    }
}

}

再來(lái)看下 AutoConfigurationImportSelector 句喷,主要是 接口的 ImportSelector 的實(shí)現(xiàn)

@Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        try {
            //1丐膝、 自動(dòng)配置的元數(shù)據(jù) spring-autocomfigure-metadata.properties
            // 自動(dòng)配置的開(kāi)啟條件
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                    .loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            // 獲取設(shè)置的自動(dòng)配置列表 spring.factories
            List<String> configurations = getCandidateConfigurations(annotationMetadata,
                    attributes);
            configurations = removeDuplicates(configurations);
            configurations = sort(configurations, autoConfigurationMetadata);
            // 獲取要排除的自動(dòng)配置列表,可以通過(guò) 注解@EnableAutoConfiguration 的exclude和
             // 配置文件設(shè)置 spring.autoconfigure.exclude key的值
            Set<String> exclusions = getExclusions(annotationMetadata, attributes);
            checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
             // 通過(guò) spring-autocomfigure-metadata.properties ConditionOnClass 條件進(jìn)行過(guò)濾
            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 的處理方式踢京,會(huì)解析 @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**的注解,我們來(lái)看下 ConditionEvaluator這個(gè) 條件計(jì)算器,會(huì)去計(jì)算出當(dāng)前這個(gè)配置類 是否要開(kāi)啟舀射,而這些 @ConditionalOn** 是依賴于 @Conditional 這個(gè)注解窘茁,如 @ConditionalOnBean 最終是通過(guò) Condition 接口來(lái)作條件選擇

@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 整合的項(xiàng)目,但大部分情況下脆烟,并不是所以的項(xiàng)目都會(huì)啟用山林,通過(guò) Condition和@Conditional 來(lái)判斷條件

  1. 判斷classPath 是否存在指定的類 @ConditionalOnClass
  2. 判斷 ApplicationContext 中是否存在指定的 Bean @ConditionalOnBean
  3. 配置環(huán)境中是否存在特定的配置項(xiàng) @ConditionalOnProperty
  4. 配置環(huán)境中指定的配置項(xiàng)是否存在指定的值

禁用配置

當(dāng)前 也是可以禁用某些我們不想要的默認(rèn)配置,如上面加載時(shí)說(shuō)到邢羔,會(huì)排除一些配置(exclude)

  1. 設(shè)置 @EnableAutoConfiguration 的exclude 配置
  2. 在配置文件增加 spring.autoconfigure.exclude 配置
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驼抹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拜鹤,更是在濱河造成了極大的恐慌框冀,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件署惯,死亡現(xiàn)場(chǎng)離奇詭異左驾,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)极谊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)诡右,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人轻猖,你說(shuō)我怎么就攤上這事帆吻。” “怎么了咙边?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵猜煮,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我败许,道長(zhǎng)王带,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任市殷,我火速辦了婚禮愕撰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘醋寝。我一直安慰自己搞挣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布音羞。 她就那樣靜靜地躺著囱桨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嗅绰。 梳的紋絲不亂的頭發(fā)上舍肠,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天搀继,我揣著相機(jī)與錄音,去河邊找鬼貌夕。 笑死律歼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的啡专。 我是一名探鬼主播险毁,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼们童!你這毒婦竟也來(lái)了畔况?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤慧库,失蹤者是張志新(化名)和其女友劉穎跷跪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體齐板,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吵瞻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了甘磨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橡羞。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖济舆,靈堂內(nèi)的尸體忽然破棺而出卿泽,到底是詐尸還是另有隱情,我是刑警寧澤滋觉,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布签夭,位于F島的核電站,受9級(jí)特大地震影響椎侠,放射性物質(zhì)發(fā)生泄漏第租。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一我纪、第九天 我趴在偏房一處隱蔽的房頂上張望煌妈。 院中可真熱鬧,春花似錦宣羊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至族操,卻和暖如春苛坚,著一層夾襖步出監(jiān)牢的瞬間比被,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工泼舱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留等缀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓娇昙,卻偏偏與公主長(zhǎng)得像尺迂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冒掌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容