溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringBoot2入門自動(dòng)配置原理源碼分析

發(fā)布時(shí)間:2022-05-30 10:43:26 來源:億速云 閱讀:160 作者:zzz 欄目:開發(fā)技術(shù)

這篇文章主要介紹“SpringBoot2入門自動(dòng)配置原理源碼分析”,在日常操作中,相信很多人在SpringBoot2入門自動(dòng)配置原理源碼分析問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”SpringBoot2入門自動(dòng)配置原理源碼分析”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

    SpringBoot自動(dòng)配置

    之前為什么會(huì)去了解一些底層注解,其實(shí)就是為了后續(xù)更好的了解 springboot 底層的一些原理,比如自動(dòng)配置原理。

    一、@SpringBootApplication

    從 MainApplication 中的@SpringBootApplication開始。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    進(jìn)入@SpringBootApplication,可以看到這是一個(gè)合成注解(紅框中是要關(guān)注的)。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    1. @SpringBootConfiguration

    這個(gè)注解干嘛的?

    直接點(diǎn)進(jìn)去,發(fā)現(xiàn)有一個(gè)@Configuration注解,那這不就是個(gè)配置類嘛。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    進(jìn)而也說明了,MainApplication 也是一個(gè)配置類。

    2. @ComponentScan

    這個(gè)已經(jīng)很熟悉了,可以指定掃描哪些 Spring 注解。

    只不過這里,加了一些其他的過濾條件,暫時(shí)不關(guān)注。

    3. @EnableAutoConfiguration

    這個(gè)是最重要的注解了,聽名字就不一般,開啟自動(dòng)配置。

    點(diǎn)進(jìn)去,發(fā)現(xiàn)也是一個(gè)合成注解(紅框需要關(guān)注)。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    (1)@AutoConfigurationPackage

    聽名字像是自動(dòng)配置包?依舊點(diǎn)進(jìn)去。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    可以看到原來是導(dǎo)入了一個(gè)叫Registrar的組件,繼續(xù)點(diǎn)進(jìn) Registrar。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    這里是利用Registrar()給容器中導(dǎo)入一系列組件,也就是批量注冊(cè)組件。

    在這里打個(gè)斷點(diǎn),debug 啟動(dòng)一下。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    registerBeanDefinitions()方法中有個(gè)傳參:

    metadata,是注解的元信息,可以看到這個(gè)注解是被標(biāo)注在com.pingguo.boot.MainApplication

    而在registerBeanDefinitions()方法體內(nèi),new 了一個(gè)AutoConfigurationPackages.PackageImports(),里面?zhèn)魅氲氖窃⒔?,通過getPackageNames()獲取到包名。

    AutoConfigurationPackages.register(
        registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0])
    );

    在 idea 中可以單獨(dú)執(zhí)行下片段代碼(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames()。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    選中右擊,再點(diǎn)擊 Evaluate。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    得到的結(jié)果就是com.pingguo.boot。為什么是這個(gè)?因?yàn)樽⒔鈽?biāo)注在MainApplication類,而這個(gè)類就屬于com.pingguo.boot。

    拿到包名之后,封裝到數(shù)組里,也就是上述代碼片段中的toArray(new String[0]),最后注冊(cè)進(jìn)去。

    所以,這里的Registrar()就是把指定的包下的所有組件批量注冊(cè)到容器中。

    (2)@Import(AutoConfigurationImportSelector.class)

    上面指定好默認(rèn)包規(guī)則之后,就需要去導(dǎo)入需要的包了,利用的是AutoConfigurationImportSelector,繼續(xù)點(diǎn)進(jìn)去看。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    這里有個(gè)selectImports方法,這個(gè)方法決定了要具體導(dǎo)入哪些,返回的是一個(gè)數(shù)組。

    方法體內(nèi),又是調(diào)用了getAutoConfigurationEntry()方法來獲取配置入口,進(jìn)而再通過getConfigurations()方法獲取具體配置,最終轉(zhuǎn)成數(shù)組返回。

    顯然getAutoConfigurationEntry()是個(gè)重點(diǎn)。

    往下翻一點(diǎn),就是getAutoConfigurationEntry()的實(shí)現(xiàn),在這里打個(gè)斷點(diǎn)(把上面的斷點(diǎn)取消掉)。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    debug重新運(yùn)行一下,往下走到getCandidateConfigurations()。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    這里是獲取所有候選配置,目前可以看到這里是共有 127 個(gè)。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    為什么是這 127 個(gè)?其實(shí)是在配置文件里寫死了,在 springboot 啟動(dòng)時(shí)候,給容器加載的所有場(chǎng)景的配置類。

    定義的位置是在這:\spring-boot-autoconfigure\2.3.4.RELEASE\spring-boot-autoconfigure-2.3.4.RELEASE.jar!\META-INF\spring.factories

    SpringBoot2入門自動(dòng)配置原理源碼分析

    雖然這些一股腦的在啟動(dòng)時(shí)候會(huì)去加載到容器,但是最終會(huì)按需開啟配置。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    比如點(diǎn)開aop,看到@ConditionalOnClass({Advice.class})這個(gè)條件,是當(dāng)存在Advice類時(shí)候才導(dǎo)入組件,但實(shí)際上這里并沒有Advice。

    這就是基于 springboot 的按條件裝配@Conditional,根據(jù)規(guī)則最終實(shí)現(xiàn)按需裝配。

    二、自動(dòng)配置示例

    分別用最終未生效、和生效的自動(dòng)配置來加深理解。

    1. 未生效的自動(dòng)配置

    比如 cache。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    可以看到CacheAutoConfiguration上是加了幾個(gè)條件裝配的。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    (1)@ConditionalOnClass({CacheManager.class})

    在 idea 中使用ctrl+N搜索一下CacheManager,發(fā)現(xiàn)是存在的,那么這個(gè)條件滿足。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    (2)@ConditionalOnBean({CacheAspectSupport.class})

    這個(gè)條件是要求容器中存在CacheAspectSupport這個(gè)組件才可以。

    現(xiàn)在來判斷一下是否存在這個(gè)組件,在 main 方法里增加測(cè)試代碼:

    ... ...
          String[] beanNamesForType = run.getBeanNamesForType(CacheAspectSupport.class);
          System.out.println("==CacheAspectSupport類型組件的數(shù)量==" + beanNamesForType.length);
    ... ...

    運(yùn)行查看輸出。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    發(fā)現(xiàn)數(shù)量等于 0,也就是不存在該類型的組件。

    也就是說@ConditionalOnBean({CacheAspectSupport.class})這個(gè)條件不滿足,所以整個(gè)類CacheAutoConfiguration里的配置都不生效。

    2. 生效的自動(dòng)配置

    之前寫過 web 的demo,那么 web 相關(guān)的配置自然是生效的,找到它。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    這里有不少后綴是**AutoConfiguration的配置,直接來看DispatcherServletAutoConfiguration。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    @Configuration(proxyBeanMethods = false):表示是一個(gè)配置類。

    @ConditionalOnWebApplication(type = Type.SERVLET):條件是否為一個(gè) web 應(yīng)用,而且是原生 SERVLET 類型的(因?yàn)閟pringboot2還有webflux),當(dāng)前滿足條件。

    @ConditionalOnClass({DispatcherServlet.class}):條件是否導(dǎo)入了DispatcherServlet類,這里也是有的。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    還有 2 個(gè)注解直接沒見過,這里不用太多關(guān)注,了解一下:

    @AutoConfigureOrder:這個(gè)配置類的配置優(yōu)先級(jí)順序。@AutoConfigureAfter:表示在xx之后才配置這個(gè)類,這里就是在配置完ServletWebServerFactoryAutoConfiguration.class后,再配置當(dāng)前的類。

    所以,類上的幾個(gè)條件都是滿足的,就可以進(jìn)一步到類中了,繼續(xù)往下找:

    SpringBoot2入門自動(dòng)配置原理源碼分析

    看到DispatcherServletConfiguration類上也有條件:

    @Conditional({DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition.class}):

    別看這么長(zhǎng),其實(shí)就是上面的一個(gè)類

    @ConditionalOnClass({ServletRegistration.class}): 這個(gè)也存在。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    @EnableConfigurationProperties({WebMvcProperties.class}):

    這個(gè)很熟悉了,使用前面剛學(xué)習(xí)完不久,它并不是條件裝配,而是用來綁定外部配置文件的,點(diǎn)進(jìn)去。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    可以看到,會(huì)與配置文件中前綴是spring.mvc的所有屬性進(jìn)行綁定。

    另外,還可以自動(dòng)把組件注冊(cè)到容器中去。

    這里可以試一下,在 main 方法里增加輸出:

    String[] beanNamesForType1 = run.getBeanNamesForType(WebMvcProperties.class);
        System.out.println("==WebMvcProperties類型組件的數(shù)量==" + beanNamesForType1.length);

    運(yùn)行一下,果然是有一個(gè):

    SpringBoot2入門自動(dòng)配置原理源碼分析

    到此,說明DispatcherServletConfiguration這個(gè)配置類也是生效的。

    繼續(xù)往下就看到方法dispatcherServlet(),而且是加了@Bean注解,就是給容器中注冊(cè)DispatcherServlet類型的組件。

    SpringBoot2入門自動(dòng)配置原理源碼分析

    這里的經(jīng)過是:

    new 一個(gè)DispatcherServlet()對(duì)象dispatcherServlet。接著對(duì)dispatcherServlet一通 set 設(shè)置。最后返回這個(gè)對(duì)象dispatcherServlet。

    在之前學(xué)習(xí) springMVC 時(shí)候,還要手動(dòng)去設(shè)置關(guān)于DispatcherServlet的一堆東西。而在 springboot 里已經(jīng)在底層設(shè)置好了,并且注冊(cè)到容器中去了,所以我們能直接使用。

    到此,關(guān)于“SpringBoot2入門自動(dòng)配置原理源碼分析”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI