首頁常見問題正文

SpringBoot自動配置的工作流程是怎樣的?

更新時間:2022-09-28 來源:黑馬程序員 瀏覽量:

什么是自動配置呢?簡單說就是springboot根據(jù)我們開發(fā)者的行為猜測你要做什么事情,然后把你要用的bean都給你準備好。聽上去是不是很神奇?其實非常簡單,。springboot咋做到的呢?就是看你導入了什么類,就知道你想干什么了。然后把你有可能要用的bean(注意是有可能)都給你加載好,你直接使用就行了,springboot把所需要的一切工作都做完了。

自動配置的意義就是加速開發(fā)效率,將開發(fā)者使用某種技術時需要使用的bean根據(jù)情況提前加載好,實現(xiàn)自動配置的效果。當然,開發(fā)者有可能需要提供必要的參數(shù),比如你要用mysql技術,導入了mysql的坐標,springboot就知道了你要做數(shù)據(jù)庫操作,一系列的數(shù)據(jù)庫操作相關的bean都給你提前聲明好,但是你要告訴springboot你到底用哪一個數(shù)據(jù)庫,P地址,端口,你不告訴spirngbootspringboot就無法幫你把自動配置相關的工作做完。

而這種思想其實就是在日常的開發(fā)過程中根據(jù)開發(fā)者的習慣慢慢抽取得到了。整體過程分為2個階段:

階段一:準備階段

1. springboot的開發(fā)人員先大量收集Spring開發(fā)者的編程習慣,整理開發(fā)過程每一個程序經(jīng)常使用的技術列表,形成一個技術集A

2. 收集常用技術(技術集A)的使用參數(shù),不管你用什么常用設置,我用什么常用設置,統(tǒng)統(tǒng)收集起來整理一下,得到開發(fā)過程中每一個技術的常用設置,形成每一個技術對應的**設置集B**

階段二:加載階段

3. springboot初始化Spring容器基礎環(huán)境,讀取用戶的配置信息,加載用戶自定義的bean和導入的其他坐標,形成初始化環(huán)境。

4. springboot將技術集A包含的所有技術在SpringBoot啟動時默認全部加載,這時肯定加載的東西有一些是無效的,沒有用的。

5. springboot會對技術集A中每一個技術約定出啟動這個技術對應的條件,并設置成按條件加載,由于開發(fā)者導入了一些bean和其他坐標,也就是與初始化環(huán)境,這個時候就可以根據(jù)這個初始化環(huán)境與springboot的技術集A進行比對了,哪個匹配上加載哪個。

6. 因為有些技術不做配置就無法工作,所以springboot開始對設置集B下手了。它統(tǒng)計出各個國家各個行業(yè)的開發(fā)者使用某個技術時最常用的設置是什么,然后把這些設置作為默認值直接設置好,并告訴開發(fā)者當前設置我已經(jīng)給你搞了一套,你要用可以直接用,這樣可以減少開發(fā)者配置參數(shù)的工作量。

7. 但是默認配置不一定能解決問題,于是springboot開放修改設置集B的接口,可以由開發(fā)者根據(jù)需要決定是否覆蓋默認配置。

以上這些僅僅是一個思想,落地到代碼實現(xiàn)階段就要好好思考一下怎么實現(xiàn)了。假定我們想自己實現(xiàn)自動配置的功能,都要做哪些工作呢?首先指定一個技術X,我們打算讓技術X具備自動配置的功能,這個技術X可以是任意功能,這個技術隸屬于上面描述的技術集A。具體的實現(xiàn)代碼如下:

public class CartoonCatAndMouse{
}

然后找出技術X使用過程中的常用配置Y,這個配置隸屬于上面表述的設置集B

yaml
cartoon:
  cat:
    name: "圖多蓋洛"
    age: 5
  mouse:
    name: "泰菲"
    age: 1

將常用配置Y設計出對應的yml配置書寫格式,然后定義一個屬性類封裝對應的配置屬性,這個過程其實就是上一節(jié)咱們做的bean的依賴屬性管理,一模一樣。

@ConfigurationProperties(prefix = "cartoon")
@Data
public class CartoonProperties {
    private Cat cat;
    private Mouse mouse;
}

最后做一個配置類,當這個類加載的時候就可以初始化對應的功能bean,并且可以加載到對應的配置。

@EnableConfigurationProperties(CartoonProperties.class)
public class CartoonCatAndMouse implements ApplicationContextAware {
    private CartoonProperties cartoonProperties;
}

當然,你也可以為當前自動配置類設置上激活條件,例如使用@CondtionOn為其設置加載條件

@ConditionalOnClass(name="org.springframework.data.redis.core.RedisOperations")
@EnableConfigurationProperties(CartoonProperties.class)
public class CartoonCatAndMouse implements ApplicationContextAware {
    private CartoonProperties cartoonProperties;
}

到這里就算配置完畢了,但是遇到了一個全新的問題,如何讓springboot啟動的時候去加載這個類呢?如果不加載的話,我們做的條件判定,做的屬性加載這些全部都失效了。

springboot自動加載

springboot為我們開放了一個配置入口,在配置目錄中創(chuàng)建META-INF目錄,并創(chuàng)建spring.factories文件,在其中添加設置,說明哪些類要啟動自動配置就可以了。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.itheima.bean.CartoonCatAndMouse

其實這個文件就做了一件事,通過這種配置的方式加載了指定的類。轉了一圈,就是個普通的bean的加載,和最初使用xml格式加載bean幾乎沒有區(qū)別,格式變了而已。那自動配置的核心究竟是什么呢?自動配置其實是一個小的生態(tài),可以按照如下思想理解:

1. 自動配置從根本上來說就是一個bean的加載

2. 通過bean加載條件的控制給開發(fā)者一種感覺,自動配置是自適應的,可以根據(jù)情況自己判定,但實際上就是最普通的分支語句的應用,這是蒙蔽我們雙眼的第一層面紗。

3. 使用bean的時候,如果不設置屬性,就有默認值,如果不想用默認值,就可以自己設置,也就是可以修改部分或者全部參數(shù),感覺這個過程好屌,也是一種自適應的形式,其實還是需要使用分支語句來做判斷的,這是蒙蔽我們雙眼的第二層面紗

4. springboot技術提前將大量開發(fā)者有可能使用的技術提前做好了,條件也寫好了,用的時候你導入了一個坐標,對應技術就可以使用了,其實就是提前幫我們把spring.factories文件寫好了,這是蒙蔽我們雙眼的第三層面紗

你在不知道自動配置這個知識的情況下,經(jīng)過上面這一二三,你當然覺得自動配置是一種特別牛的技術,但是一窺究竟后發(fā)現(xiàn),也就那么回事。而且現(xiàn)在springboot程序啟動時,在后臺偷偷的做了這么多次檢測,這么多種情況判定,不用問了,效率一定是非常低的,畢竟它要檢測100余種技術是否在你程序中使用。

總結

1. springboot啟動時先加載spring.factories文件中的org.springframework.boot.autoconfigure.EnableAutoConfiguration配置項,將其中配置的所有的類都加載成bean

2. 在加載bean的時候,bean對應的類定義上都設置有加載條件,因此有可能加載成功,也可能條件檢測失敗不加載bean

3. 對于可以正常加載成bean的類,通常會通過@EnableConfigurationProperties注解初始化對應的配置屬性類并加載對應的配置

4. 配置屬性類上通常會通過@ConfigurationProperties加載指定前綴的配置,當然這些配置通常都有默認值。如果沒有默認值,就強制你必須配置后使用了


分享到:
在線咨詢 我要報名
和我們在線交談!