Spring Boot 自動配置之@EnableAutoConfiguration

Spring Boot 啟動類上一個 @SpringBootApplication 注解是

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

三個注解組成的一個復(fù)合注解夭问。其中 @SpringBootConfiguration 其實也是和@Configuration 注解組成的一個組合注解,功能也是和 @Configuration 相同苟穆;@ComponentScan 這個注解是標(biāo)注需要掃描的包。今天著重說一下 @EnableAutoConfiguration 注解唱星。


其實 @EnableAutoConfiguration 注解也和其它 @Enable*
注解一脈相乘的雳旅,簡單說一下就是借助 @Import 的支持,收集和注冊特定場景相關(guān)的Bean的定義:比如:@EnableAspectJAutoProxy 就是通過@Import 注解動態(tài)的將Bean注冊到 SpringIoc
容器中间聊,而@EnableAutoConfiguration 是借助 @Import 把所有符合條件的 Bean 加載到
SpringIoc 容器中攒盈。

參看上一篇文章 Spring Boot
自動配置之@Enable*與@Import注解

1、@EnableAutoConfiguration 也是一個組合注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};
    
    String[] excludeName() default {};

}

其中最重要的是 @Import(AutoConfigurationImportSelector.class)注解哎榴。借助AutoConfigurationImportSelector 型豁,@EnableAutoConfiguration 幫助Spring Boot 應(yīng)用將所有符合條件的 @Configuration 配置加載到當(dāng)前IoC容器中。而最主要的還是借助于 Spring 框架一的一個工具類:SpringFactoriesLoader 將 META-INF/spring.factories加載配置尚蝌,spring.factories 文件是一個典型的properties配置文件迎变,配置的格式仍然是Key = Value 的形式,中不過 Key 和 Value 都是Java的完整類名飘言。比如:org.springframework.data.repository.core.support.RepositoryFactorySupport=org.springframework.data.jpa.repository.support.JpaRepositoryFactory

2衣形、AutoConfigurationImportSelector 源碼

@Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader); //1
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
                autoConfigurationMetadata, annotationMetadata); //2
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

  • 1.獲取注解信息
  • 2.獲取所有配置列表

其中 AutoConfigurationMetadataLoader.loadMetadata方法源碼

public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
        return loadMetadata(classLoader, PATH);
    }

    static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
        try {
            Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
                    : ClassLoader.getSystemResources(path);
            Properties properties = new Properties();
            while (urls.hasMoreElements()) {
                properties.putAll(PropertiesLoaderUtils
                        .loadProperties(new UrlResource(urls.nextElement())));
            }
            return loadMetadata(properties);
        }
        catch (IOException ex) {
            throw new IllegalArgumentException(
                    "Unable to load @ConditionalOnClass location [" + path + "]", ex);
        }
    }

getAutoConfigurationEntry 方法:

protected AutoConfigurationEntry getAutoConfigurationEntry(
            AutoConfigurationMetadata autoConfigurationMetadata,
            AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        //1.
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        //2.
        List<String> configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        //3.
        configurations = removeDuplicates(configurations);
        //4.
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        //5.
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }

  • 1.獲取注解上所有屬性信息
  • 2.獲取候選配置列表 [核心步驟]
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
        Assert.notEmpty(configurations,
                "No auto configuration classes found in META-INF/spring.factories. If you "
                        + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }
    
    通過SpringFactoriesLoader.loadFactoryNames獲取配置信息
  • 3.去重
  • 4.配置exclude 信息去除不需要的
  • 5.派發(fā)事件
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市姿鸿,隨后出現(xiàn)的幾起案子谆吴,更是在濱河造成了極大的恐慌,老刑警劉巖苛预,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件句狼,死亡現(xiàn)場離奇詭異,居然都是意外死亡热某,警方通過查閱死者的電腦和手機腻菇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門胳螟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人筹吐,你說我怎么就攤上這事糖耸。” “怎么了骏令?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長垄提。 經(jīng)常有香客問我榔袋,道長,這世上最難降的妖魔是什么铡俐? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任凰兑,我火速辦了婚禮,結(jié)果婚禮上审丘,老公的妹妹穿的比我還像新娘吏够。我一直安慰自己,他們只是感情好滩报,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布锅知。 她就那樣靜靜地躺著,像睡著了一般脓钾。 火紅的嫁衣襯著肌膚如雪售睹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天可训,我揣著相機與錄音昌妹,去河邊找鬼。 笑死握截,一個胖子當(dāng)著我的面吹牛飞崖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谨胞,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼固歪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胯努?” 一聲冷哼從身側(cè)響起昼牛,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤捉兴,失蹤者是張志新(化名)和其女友劉穎国葬,沒想到半個月后拷获,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乾闰,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蒿赢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年杠茬,在試婚紗的時候發(fā)現(xiàn)自己被綠了贵扰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菊霜。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖脊另,靈堂內(nèi)的尸體忽然破棺而出导狡,到底是詐尸還是另有隱情,我是刑警寧澤偎痛,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布旱捧,位于F島的核電站,受9級特大地震影響踩麦,放射性物質(zhì)發(fā)生泄漏枚赡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一谓谦、第九天 我趴在偏房一處隱蔽的房頂上張望贫橙。 院中可真熱鬧,春花似錦反粥、人聲如沸卢肃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莫湘。三九已至,卻和暖如春郑气,著一層夾襖步出監(jiān)牢的瞬間逊脯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工竣贪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留军洼,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓演怎,卻偏偏與公主長得像匕争,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子爷耀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

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