EnableAutoConfiguration注解的工作原理

demo

自己定義一個(gè)外部項(xiàng)目奴紧,core-bean搪花,依賴(lài)如下,

<artifactId>core-bean</artifactId>
<packaging>jar</packaging>

<dependencies>
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context</artifactId>
       <version>4.3.9.RELEASE</version>
   </dependency>
</dependencies>

然后定義一個(gè)Cat類(lèi)薯嗤,

public class Cat {
}
package core.bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {

    @Bean
    public Cat cat(){
        return new Cat();
    }
}

我們知道這樣就將Cat類(lèi)裝配到Spring容器了顽爹。

再定義一個(gè)springboot項(xiàng)目,加入core-bean依賴(lài)骆姐,依賴(lài)如下:

<artifactId>springboot-enableAutoConfiguration</artifactId>
<packaging>jar</packaging>

<dependencies>
     <dependency>
            <groupId>com.zhihao.miao</groupId>
            <artifactId>core-bean</artifactId>
            <version>1.0-SNAPSHOT</version>
      </dependency>
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
     </dependency>
</dependencies>

啟動(dòng)類(lèi)啟動(dòng):

@EnableAutoConfiguration
@ComponentScan
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        Cat cat = context.getBean(Cat.class);
        System.out.println(cat);
    }
}

發(fā)現(xiàn)Cat類(lèi)并沒(méi)有納入到springboot-enableAutoConfiguration項(xiàng)目中镜粤。

解決方案,
在core-bean項(xiàng)目resource下新建文件夾META-INF玻褪,在文件夾下面新建spring.factories文件肉渴,文件中配置,key為自定配置類(lèi)EnableAutoConfiguration的全路徑带射,value是配置類(lèi)的全路徑

org.springframework.boot.autoconfigure.EnableAutoConfiguration=core.bean.MyConfig

啟動(dòng)springboot-enableAutoConfiguration項(xiàng)目同规,打印結(jié)果:

原理分析

進(jìn)入EnableAutoConfiguration注解源碼,發(fā)現(xiàn)是導(dǎo)入EnableAutoConfigurationImportSelector類(lèi)窟社,



跟到最后發(fā)現(xiàn)繼承了ImportSelector接口券勺,之前我們講過(guò)Springboot @Enable*注解的工作原理ImportSelector接口的selectImports返回的數(shù)組(類(lèi)的全類(lèi)名)都會(huì)被納入到spring容器中。

其在AutoConfigurationImportSelector類(lèi)中的selectImports實(shí)現(xiàn)灿里,進(jìn)入org.springframework.boot.autoconfigure.AutoConfigurationImportSelector類(lèi)关炼,

進(jìn)入getCandidateConfigurations方法



getCandidateConfigurations會(huì)到classpath下的讀取META-INF/spring.factories文件的配置,并返回一個(gè)字符串?dāng)?shù)組匣吊。

調(diào)試的時(shí)候讀取到了core.bean.MyConfig儒拂,也讀到了一些其他的配置,下面會(huì)講色鸳。

圖片.png

具體的就不細(xì)說(shuō)了社痛,有興趣的朋友可以自己調(diào)試一下。
META-INF/spring.factories還可以配置多個(gè)配置類(lèi)命雀。

比如我們?cè)赾ore-bean下在定義二個(gè)類(lèi)蒜哀,

package core.bean;

public class Dog {
}
package core.bean;

public class People {
}
package core.bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Myconfig2 {

    @Bean
    public Dog dog(){
        return new Dog();
    }
}

修改META-INF/spring.factories下的配置,

org.springframework.boot.autoconfigure.EnableAutoConfiguration=core.bean.MyConfig,core.bean.Myconfig2,core.bean.People

修改springboot-enableAutoConfiguration項(xiàng)目的啟動(dòng)類(lèi):

package com.zhihao.miao;

import core.bean.Cat;
import core.bean.Dog;
import core.bean.People;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@EnableAutoConfiguration
@ComponentScan
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        Cat cat = context.getBean(Cat.class);
        System.out.println(cat);
        Dog dog = context.getBean(Dog.class);
        System.out.println(dog);
        People people = context.getBean(People.class);
        System.out.println(people);
    }
}

打印結(jié)果如下:


發(fā)現(xiàn)都納入到spring容器中了咏雌。

可以配置spring.boot.enableautoconfiguration=false禁用自動(dòng)配置凡怎,這樣不會(huì)啟動(dòng)自動(dòng)配置了校焦,默認(rèn)是true。還可以排出一些自動(dòng)配置類(lèi)统倒,可以在EnableAutoConfiguration注解加入?yún)?shù)寨典,這邊不做過(guò)多解釋。

圖片.png

總結(jié),@EnableAutoConfiguration 作用
從classpath中搜索所有META-INF/spring.factories配置文件然后房匆,將其中org.springframework.boot.autoconfigure.EnableAutoConfiguration key對(duì)應(yīng)的配置項(xiàng)加載到spring容器
只有spring.boot.enableautoconfiguration為true(默認(rèn)為true)的時(shí)候耸成,才啟用自動(dòng)配置
@EnableAutoConfiguration還可以進(jìn)行排除,排除方式有2中浴鸿,一是根據(jù)class來(lái)排除(exclude)井氢,二是根據(jù)class name(excludeName)來(lái)排除
其內(nèi)部實(shí)現(xiàn)的關(guān)鍵點(diǎn)有
1)ImportSelector 該接口的方法的返回值都會(huì)被納入到spring容器管理中
2)SpringFactoriesLoader 該類(lèi)可以從classpath中搜索所有META-INF/spring.factories配置文件,并讀取配置

springboot內(nèi)部如何使用@EnableAutoConfiguration注解

我們點(diǎn)進(jìn)去spring-boot-autoconfigure中的META-INF下的spring.factories文件岳链,發(fā)現(xiàn)spring.factories文件中配置了好多的配置類(lèi)花竞,在將這些依賴(lài)依賴(lài)到自己的項(xiàng)目中會(huì)將其都納入到spring容器中,不過(guò)這些類(lèi)好多都是配合@Conditional***等注解一起工作的掸哑。

舉個(gè)例子:
在springboot-enableAutoConfiguration加入Gson依賴(lài):

<dependency>
      <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
</dependency>
GsonAutoConfiguration源碼

如果我們不在項(xiàng)目中配置约急,spring-boot-autoconfigure會(huì)自動(dòng)幫我們裝配一個(gè)對(duì)象實(shí)例名為gson的Gson實(shí)例。如果自己裝配那么就使用自己裝配的Gson實(shí)例苗分。

啟動(dòng)測(cè)試類(lèi):

package com.zhihao.miao;

import com.google.gson.Gson;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        System.out.println(context.getBeansOfType(Gson.class));
    }
}

此時(shí)自己沒(méi)有去配置Gson對(duì)象厌蔽,

如果自己配置了,測(cè)試代碼如下摔癣,啟動(dòng):

package com.zhihao.miao;

import com.google.gson.Gson;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

    @Bean
    public Gson createGson(){
        return new Gson();
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        System.out.println(context.getBeansOfType(Gson.class));
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奴饮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子择浊,更是在濱河造成了極大的恐慌戴卜,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琢岩,死亡現(xiàn)場(chǎng)離奇詭異叉瘩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)粘捎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)危彩,“玉大人攒磨,你說(shuō)我怎么就攤上這事√阑眨” “怎么了娩缰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)谒府。 經(jīng)常有香客問(wèn)我拼坎,道長(zhǎng)浮毯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任泰鸡,我火速辦了婚禮债蓝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盛龄。我一直安慰自己饰迹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布余舶。 她就那樣靜靜地躺著啊鸭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匿值。 梳的紋絲不亂的頭發(fā)上赠制,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音挟憔,去河邊找鬼钟些。 笑死,一個(gè)胖子當(dāng)著我的面吹牛曲楚,可吹牛的內(nèi)容都是我干的厘唾。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼龙誊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抚垃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起趟大,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鹤树,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后逊朽,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體罕伯,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年叽讳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了追他。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岛蚤,死狀恐怖邑狸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涤妒,我是刑警寧澤单雾,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響硅堆,放射性物質(zhì)發(fā)生泄漏屿储。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一渐逃、第九天 我趴在偏房一處隱蔽的房頂上張望够掠。 院中可真熱鬧,春花似錦朴乖、人聲如沸祖屏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)袁勺。三九已至,卻和暖如春畜普,著一層夾襖步出監(jiān)牢的瞬間期丰,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工吃挑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钝荡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓舶衬,卻偏偏與公主長(zhǎng)得像埠通,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子逛犹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

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