更新時間:2022-09-28 來源:黑馬程序員 瀏覽量:
什么是自動配置呢?簡單說就是springboot根據(jù)我們開發(fā)者的行為猜測你要做什么事情,然后把你要用的bean都給你準(zhǔn)備好。聽上去是不是很神奇?其實(shí)非常簡單,。springboot咋做到的呢?就是看你導(dǎo)入了什么類,就知道你想干什么了。然后把你有可能要用的bean(注意是有可能)都給你加載好,你直接使用就行了,springboot把所需要的一切工作都做完了。
自動配置的意義就是加速開發(fā)效率,將開發(fā)者使用某種技術(shù)時需要使用的bean根據(jù)情況提前加載好,實(shí)現(xiàn)自動配置的效果。當(dāng)然,開發(fā)者有可能需要提供必要的參數(shù),比如你要用mysql技術(shù),導(dǎo)入了mysql的坐標(biāo),springboot就知道了你要做數(shù)據(jù)庫操作,一系列的數(shù)據(jù)庫操作相關(guān)的bean都給你提前聲明好,但是你要告訴springboot你到底用哪一個數(shù)據(jù)庫,P地址,端口,你不告訴spirngbootspringboot就無法幫你把自動配置相關(guān)的工作做完。
而這種思想其實(shí)就是在日常的開發(fā)過程中根據(jù)開發(fā)者的習(xí)慣慢慢抽取得到了。整體過程分為2個階段:
1. springboot的開發(fā)人員先大量收集Spring開發(fā)者的編程習(xí)慣,整理開發(fā)過程每一個程序經(jīng)常使用的技術(shù)列表,形成一個技術(shù)集A
2. 收集常用技術(shù)(技術(shù)集A)的使用參數(shù),不管你用什么常用設(shè)置,我用什么常用設(shè)置,統(tǒng)統(tǒng)收集起來整理一下,得到開發(fā)過程中每一個技術(shù)的常用設(shè)置,形成每一個技術(shù)對應(yīng)的**設(shè)置集B**
3. springboot初始化Spring容器基礎(chǔ)環(huán)境,讀取用戶的配置信息,加載用戶自定義的bean和導(dǎo)入的其他坐標(biāo),形成初始化環(huán)境。
4. springboot將技術(shù)集A包含的所有技術(shù)在SpringBoot啟動時默認(rèn)全部加載,這時肯定加載的東西有一些是無效的,沒有用的。
5. springboot會對技術(shù)集A中每一個技術(shù)約定出啟動這個技術(shù)對應(yīng)的條件,并設(shè)置成按條件加載,由于開發(fā)者導(dǎo)入了一些bean和其他坐標(biāo),也就是與初始化環(huán)境,這個時候就可以根據(jù)這個初始化環(huán)境與springboot的技術(shù)集A進(jìn)行比對了,哪個匹配上加載哪個。
6. 因?yàn)橛行┘夹g(shù)不做配置就無法工作,所以springboot開始對設(shè)置集B下手了。它統(tǒng)計出各個國家各個行業(yè)的開發(fā)者使用某個技術(shù)時最常用的設(shè)置是什么,然后把這些設(shè)置作為默認(rèn)值直接設(shè)置好,并告訴開發(fā)者當(dāng)前設(shè)置我已經(jīng)給你搞了一套,你要用可以直接用,這樣可以減少開發(fā)者配置參數(shù)的工作量。
7. 但是默認(rèn)配置不一定能解決問題,于是springboot開放修改設(shè)置集B的接口,可以由開發(fā)者根據(jù)需要決定是否覆蓋默認(rèn)配置。
以上這些僅僅是一個思想,落地到代碼實(shí)現(xiàn)階段就要好好思考一下怎么實(shí)現(xiàn)了。假定我們想自己實(shí)現(xiàn)自動配置的功能,都要做哪些工作呢?首先指定一個技術(shù)X,我們打算讓技術(shù)X具備自動配置的功能,這個技術(shù)X可以是任意功能,這個技術(shù)隸屬于上面描述的技術(shù)集A。具體的實(shí)現(xiàn)代碼如下:
public class CartoonCatAndMouse{ }
然后找出技術(shù)X使用過程中的常用配置Y,這個配置隸屬于上面表述的設(shè)置集B
yaml cartoon: cat: name: "圖多蓋洛" age: 5 mouse: name: "泰菲" age: 1
將常用配置Y設(shè)計出對應(yīng)的yml配置書寫格式,然后定義一個屬性類封裝對應(yīng)的配置屬性,這個過程其實(shí)就是上一節(jié)咱們做的bean的依賴屬性管理,一模一樣。
@ConfigurationProperties(prefix = "cartoon") @Data public class CartoonProperties { private Cat cat; private Mouse mouse; }
最后做一個配置類,當(dāng)這個類加載的時候就可以初始化對應(yīng)的功能bean,并且可以加載到對應(yīng)的配置。
@EnableConfigurationProperties(CartoonProperties.class) public class CartoonCatAndMouse implements ApplicationContextAware { private CartoonProperties cartoonProperties; }
當(dāng)然,你也可以為當(dāng)前自動配置類設(shè)置上激活條件,例如使用@CondtionOn為其設(shè)置加載條件
@ConditionalOnClass(name="org.springframework.data.redis.core.RedisOperations") @EnableConfigurationProperties(CartoonProperties.class) public class CartoonCatAndMouse implements ApplicationContextAware { private CartoonProperties cartoonProperties; }
到這里就算配置完畢了,但是遇到了一個全新的問題,如何讓springboot啟動的時候去加載這個類呢?如果不加載的話,我們做的條件判定,做的屬性加載這些全部都失效了。
springboot為我們開放了一個配置入口,在配置目錄中創(chuàng)建META-INF目錄,并創(chuàng)建spring.factories文件,在其中添加設(shè)置,說明哪些類要啟動自動配置就可以了。
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.itheima.bean.CartoonCatAndMouse
其實(shí)這個文件就做了一件事,通過這種配置的方式加載了指定的類。轉(zhuǎn)了一圈,就是個普通的bean的加載,和最初使用xml格式加載bean幾乎沒有區(qū)別,格式變了而已。那自動配置的核心究竟是什么呢?自動配置其實(shí)是一個小的生態(tài),可以按照如下思想理解:
1. 自動配置從根本上來說就是一個bean的加載
2. 通過bean加載條件的控制給開發(fā)者一種感覺,自動配置是自適應(yīng)的,可以根據(jù)情況自己判定,但實(shí)際上就是最普通的分支語句的應(yīng)用,這是蒙蔽我們雙眼的第一層面紗。
3. 使用bean的時候,如果不設(shè)置屬性,就有默認(rèn)值,如果不想用默認(rèn)值,就可以自己設(shè)置,也就是可以修改部分或者全部參數(shù),感覺這個過程好屌,也是一種自適應(yīng)的形式,其實(shí)還是需要使用分支語句來做判斷的,這是蒙蔽我們雙眼的第二層面紗
4. springboot技術(shù)提前將大量開發(fā)者有可能使用的技術(shù)提前做好了,條件也寫好了,用的時候你導(dǎo)入了一個坐標(biāo),對應(yīng)技術(shù)就可以使用了,其實(shí)就是提前幫我們把spring.factories文件寫好了,這是蒙蔽我們雙眼的第三層面紗
你在不知道自動配置這個知識的情況下,經(jīng)過上面這一二三,你當(dāng)然覺得自動配置是一種特別牛的技術(shù),但是一窺究竟后發(fā)現(xiàn),也就那么回事。而且現(xiàn)在springboot程序啟動時,在后臺偷偷的做了這么多次檢測,這么多種情況判定,不用問了,效率一定是非常低的,畢竟它要檢測100余種技術(shù)是否在你程序中使用。
1. springboot啟動時先加載spring.factories文件中的org.springframework.boot.autoconfigure.EnableAutoConfiguration配置項,將其中配置的所有的類都加載成bean
2. 在加載bean的時候,bean對應(yīng)的類定義上都設(shè)置有加載條件,因此有可能加載成功,也可能條件檢測失敗不加載bean
3. 對于可以正常加載成bean的類,通常會通過@EnableConfigurationProperties注解初始化對應(yīng)的配置屬性類并加載對應(yīng)的配置
4. 配置屬性類上通常會通過@ConfigurationProperties加載指定前綴的配置,當(dāng)然這些配置通常都有默認(rèn)值。如果沒有默認(rèn)值,就強(qiáng)制你必須配置后使用了