(上篇)Spring自動裝配倆種方式的系統(tǒng)分析以及相關(guān)問題點的探究——starter篇

寫在開頭

好久沒有去寫博客了童本,最近一年發(fā)生了太多事情炫狱,感覺自己需要好好沉淀和消化這些,也更加需要去思考未來的路該如何去走耿芹,趁著這段時間比較空閑恶导,寫幾篇關(guān)于spring的知識點浆竭,也順便去熟悉下自己的知識棧。同時加強一下自己的寫作“基本功”甲锡。

這篇文章主要講什么兆蕉?

這篇文章主要會圍繞以下倆個點來進行探究:

  1. spring自動裝配的倆種方式的規(guī)范以及倆種方式的區(qū)別和相似點
  2. spring自動裝配的一些特性和注意點以及springboot自身對不同組件選用不同的裝配模式的原因

可能上面的說法太過抽象,沒關(guān)系缤沦,下面我會結(jié)合生動形象的例子來為大家闡述我今天所講的內(nèi)容虎韵。

spring自動裝配倆種方式

在去了解spring自動裝配之前,有個小的知識點需要大家掌握缸废,springboot項目中包蓝,會優(yōu)先掃描項目工程的包路徑去注入到spring容器中驶社,其次才會掃描注入大家一直所聽說的“約定大于配置”中的spring自身的一些組件。
舉個例子:

如果你的工程路徑所在的包名為:com.xxxx.web测萎,springboot啟動類也在這個類下亡电,那么springboot項目啟動后會優(yōu)先掃描當前項目classpath路徑下所有com.xxxx.web包(包括當前工程以及依賴過來的所有第三方j(luò)ar)的所有spring的bean(類上含有spring容器注解的class),加入到容器硅瞧,然后會再去解析啟動類上的spring自動裝配的注解份乒。這個理解是很重要的一點,很多注入失敗或者spring特性應(yīng)用失敗腕唧,都跟這個有很大關(guān)系或辖。如果具體想要了解詳細的請看我之前的一篇文章springbean的加載順序,好的枣接,話不多說颂暇,我們趕緊進入正題。

1.starter模式

自動裝配的starter模式是最經(jīng)典的方式之一但惶,為何說經(jīng)典耳鸯,因為他真正實現(xiàn)了可插拔模式,想用使用某個功能組件膀曾,就引入相應(yīng)的pom坐標县爬,之后所有的操作都有spring來幫你完成,包括bean的注入妓肢,資源的建立等等捌省。
當然,我說了這些優(yōu)點肯定不夠權(quán)威碉钠,畢竟我不是spring作者纲缓,那么我們看下spring官網(wǎng)的描述

1.1 spring官方描述

image.png

雖然我的英語真的很爛,我就中式解讀下他這個說的啥意思:

  1. starters是一組依賴的聚合體喊废,你可以使用它在你的項目中
  2. 你可以使用它里面涉及到spring的所提供的一站式功能(one-stop)祝高,不需要再去網(wǎng)上或者其他地方進行ctrl+c、ctrl+v了(鄙視我們有木有)污筷。然后他舉了個例子工闺,如果你想使用jpa,那么就引用data-jpa組件就好了
  3. 關(guān)于命名的解釋瓣蛀,官方使用spring-boot-starter開頭陆蟆,第三方或個人建議使用xxx-spring-boot-starter開頭,這個沒什么好說的

怎么樣惋增,感覺翻譯的還挺言簡意賅吧

那么springboot官方有哪些組件呢叠殷,我們從官網(wǎng)上也可以看一下:


image.png

image.png

image.png

可以看到,spring提供了相當之數(shù)量的starter組件诈皿,涵蓋各個領(lǐng)域和中間件林束,這里就不做過多分析像棘,貼下官網(wǎng)的地址,大家可以自行去查看壶冒。SpringBoot Starters官網(wǎng)地址

1.2 簡單案例

看了上面官網(wǎng)的demo缕题,下面我來進行操作一個案例,展示如何構(gòu)建一個自己的starter

  1. 首先創(chuàng)建一個maven項目工程胖腾,用來被第三方進行依賴


    image.png

可以看到我建了一個父工程烟零,名叫xxq-spring-starters,然后新建了一個子模塊咸作,叫做spring-boot-starter-test1瓶摆,這個就是我創(chuàng)建的starter,當然名字沒有按照spring建議的去命名性宏,pom文件只需要引入一個autoconfigure依賴即可

  1. 創(chuàng)建自己的依賴bean,可以看到下圖状飞,我這個依賴毫胜,只有一個TestService,我需要將這個bean提供給第三方使用


    image.png
  2. 編寫自己的依賴配置诬辈,我這邊通過javaconfig的形式去配置了我的testService的注入和相關(guān)條件酵使,在沒有testService的情況下才允許注入。這是spring提供的一個特性


    image.png
  3. 在meta-inf中配置自動裝配的spi焙糟。這一步所作的意義就是spring容器在初始化的時候口渔,會基于spi機制掃描所有jar包下的META-INF路徑下的spring.factories文件中的自動裝配的配置類,然后進行解析注入


    image.png
  4. 最后一步穿撮,進行打包部署缺脉。

上述五步做完之后,在springboot項目中引入這個jar就可以自動注入TestService這個bean了悦穿。
我這邊也是新建了springboot簡單項目攻礼,用于測試。

image.png

運行結(jié)果:

image.png

可以看到栗柒,打印了初始化的構(gòu)造函數(shù)礁扮,意味著TestService這個bean就被自動注入進來了。我們僅在新項目中引用了一個pom瞬沦,其他的什么都沒做太伊。這就是starter的神奇之處,能幫我們把一些公用的可以復(fù)用的代碼和架構(gòu)進行整合成一個單獨項目逛钻,所有想要使用這些功能的其他項目僚焦,就直接引入就可以了。

上面通過舉了一個簡單例子绣的,演示了如何創(chuàng)建一個starter叠赐,那么這時候有個問題來了欲账,我上面的步驟流程是創(chuàng)建starter的規(guī)范嗎?又或者網(wǎng)絡(luò)上那么多講解springstarter的芭概,誰是規(guī)范赛不,該聽哪個,學(xué)哪個的呢罢洲,這時候我的做法就是踢故,誰都看,誰都學(xué)惹苗,最后通過官方demo驗證殿较。下面我通過官方代碼去看什么是標準

1.3 spring官方案例

  1. 首先我們選一個spring官方的starter去研究,這里我選擇的是spring-boot-starter-data-redis
image.png
  1. 我們進行分析這個starter的工程模塊桩蓉,打開spring-boot-starter-data-redis的結(jié)構(gòu)
image.png

我們看到淋纲,spring官方的好像跟我們不太一樣,一眼至少能看出來倆個不一樣

  • 它沒有其他代碼院究,只有一個pom文件洽瞬,沒有我們上面的什么Configuration的配置,按道理這里應(yīng)該有RedisAutoConfiguration之類的配置代碼业汰,但是沒有伙窃。
  • 它的pom文件也沒有引入autoconfigure依賴,而是和redis比較緊密的spring-data-redis模塊样漆。(補充一個知識點为障,對于之前沒有接觸過springframework而直接使用spring-boot-framework的,對這個spring-data-redis會很陌生放祟,其實spring-data-redis才是正統(tǒng)的spring接入redis中間件的jar包鳍怨,它是屬于spring-data中的一部分,脫離springboot也能生存舞竿,并且能直接和springframework進行緊密協(xié)作京景。而spring-boot-starter-data-redis僅僅是做了一些封裝,通過我們看到的骗奖,它連代碼都沒确徙,就是套了個殼,他為什么要套個殼呢执桌,其實還是為了方便spring-boot的自動注入做的一個中間層)

那么問題來了鄙皇,為什么spring官方的和我不一樣呢,是我寫的不對仰挣,還是我找的示例不對呢伴逸,帶著這個問題,我們深入去分析下spring的自動裝配到底是怎么做的膘壶。

首先错蝴,我們知道redis如果要進行自動裝配洲愤,必然有Configuration類,為什么說必然有顷锰,因為所有spring接入的第三方組建柬赐,都會有這個配置類,那么既然redis這個配置類不在starter里面官紫,那么肯定在某個地方存在肛宋。我們進行全局模糊搜索

image.png

發(fā)現(xiàn)確實存在這個配置類,但是它所屬的路徑很奇怪束世,竟然在spring-boot-autoconfigure中酝陈,這明顯和我上面創(chuàng)建starter的步驟和流程不一樣,那么這個spring-boot-autoconfigure有什么作用毁涉,他又為什么包含了redisAutoConfiguration沉帮,同時又是怎么自動裝配redis中間件的呢,帶著這么三個問題贫堰,我們進行深入分析遇西。

  1. 首先分析第一個問題,spring-boot-autoconfigure是什么严嗜?
    我們切入到這個jar包中去看項目結(jié)構(gòu),如下圖所示:


    image.png

我們可以看到洲敢,這個spring-boot-autoconfigure包含的不僅僅是redis相關(guān)的配置類漫玄,基本涵蓋了spring提供的所有組件能力的配置類,是springboot核心能力的聚合压彭。

  1. 它又為什么包含了redisAutoConfiguration這個配置類睦优,它可以不包含嗎?答:可以壮不,它可以不包含汗盘,就像我們的寫法一樣,單獨拎出來去寫询一。這就跟我們上面所提到的疑問一樣隐孽,為什么我們的寫法和spring官方的starter寫法不一樣呢,我們可以使用spring官方的寫法去寫我們自己的starter嘛健蕊?
    答:不可以菱阵。為什么?因為我們構(gòu)建自己的starter只能是新建工程去做缩功,如果要想使用spring官方這種做法晴及,那么我們需要修改springboot源碼,把自己的代碼放到spring源碼中重新編譯打包嫡锌,定制自己企業(yè)級的標準虑稼,這么做的成本太大琳钉,而且也沒必要,因此我們不使用spring官方的做法蛛倦,使用我們自己的構(gòu)建方式歌懒,那么我們的寫法是錯的嗎?或者為什么使用這種寫法呢胰蝠,帶著這個問題我們分析第三個問題歼培。

  2. 它是如何自動裝配了redis的呢
    我們知道,如果要想使一個配置類基于starter模式去注入茸塞,最后都要使用spring的spi機制使得這個自動裝配類被加載和解析躲庄。

image.png

我們看到配置類上有一個ConditionalOnClass注解,這個注解見面知意钾虐。當classpath中存在這個class的時候噪窘,這個配置類生效,那么我們看JedisConnection.class, RedisOperations.class, Jedis.class 這三個類都是哪個包下的

image.png

因此我們可以大致得出一個構(gòu)思效扫,springboot先是把所有內(nèi)置組件的自動裝配類封裝到autoconfigure的jar包中倔监,然后采用ConditionalOnClass來判斷每一個自動裝配類是否生效,當我們引入某一個組件的時候菌仁,例如spring-boot-starter-data-redis浩习,其中的pom文件會自動引入spring-data-redis依賴,而這個依賴中存在著是否開啟這個中間件的class類济丘。正好和spring-boot-autoconfigure中的裝配類中的條件前后呼應(yīng)谱秽,達到自動注入的功能。

好的摹迷,既然我們已經(jīng)分析這一層的因果關(guān)系疟赊,那么,最終的redisAutoConfiguration是在哪里被spi機制配置呢峡碉,其實大概也能猜出近哟,這個配置類在哪,基本就是在那個jar包中進行spi配置鲫寄,如下圖所示:

image.png

相信這張圖能夠清晰的展現(xiàn)出spring是如何最終將redisAutoConfiguration和spi機制結(jié)合起來的吉执,也是和我們之前的案例中的做法類似,是寫在MTA-INF中地来,唯一不同的是鼠证,我們是在starter包下面寫的,而它是在autoconfigure的jar包中寫的靠抑。

以上總結(jié):
通過我們自己的案例和分析spring官方的做法量九,我們知道了差異和相似點。那么我相信有很多有潔癖的開發(fā)同學(xué),肯定會說:我就覺得你這種寫法不好荠列,我就喜歡官方的寫法类浪。那么我們是否依舊學(xué)習(xí)官方的這種做法呢。答:雖然我上面說是不可以的肌似,但是實際上是可以的费就,但是會有些區(qū)別。

1.4 借鑒官方創(chuàng)建標準starter

  1. 首先我們分析下spring-boot-autoconfigure這個jar包川队,我們上面的分析發(fā)現(xiàn)力细,spring把自己的所有內(nèi)置組件的Configuration配置類都放在這里。那么我們也依葫蘆畫瓢去做這么一個autoconfigure包

  2. 在創(chuàng)建這個包之前固额,我們還得分析下眠蚂,需要引入哪些依賴,有同學(xué)會問斗躏,我可以什么都不引入逝慧,單純?nèi)プ鲎约旱慕M件嗎?或者看我上面的demo是引入了spring-boot-autoconfigure這個jar啄糙,那么我們自己模仿的可以不引入嗎笛臣?答:是不行的,首先我們最需要依賴的EnableAutoConfiguration注解在這個jar包中隧饼,所以需要要引入這個jar


    image.png
  3. 經(jīng)過上面?zhèn)z點論證沈堡,我們準備創(chuàng)建自己的autoconfigure包,在創(chuàng)建autoconfigure之前燕雁,我們注意一個點踱蛀,類似于redis,我們需要有redis自身的類贵白,類似于spring-data-redis這種,因此崩泡,我們需要先創(chuàng)建spring-test1表示是自己的一個測試包


    pom文件
image.png

spring-xxq-test1工程很簡單禁荒,就只有一個TestService,也沒有任何依賴角撞。

  1. 創(chuàng)建autoconfigure呛伴,如下


    pom文件
image.png
image.png

注意,我們這里引入的spring-boot-test1只是為了實現(xiàn)ConditionalOnClass谒所,因此optional一定要設(shè)置為true热康,表示依賴不傳遞,這也是為了和spring官方做法保持一致劣领,還有一點姐军。這里的包的命名不要和我們測試boot工程的啟動類的命名路徑重合,我們測試的boot工程啟動類在com.xxq包路徑下,因此我們這邊將autoconfigure的包名設(shè)置為了com.test路徑奕锌,因為如果autoconfigure也在com.xxq下著觉,默認就會被spring啟動掃描,這會對測試造成干擾惊暴。

  1. 創(chuàng)建我們的starter


    pom文件

可以看到饼丘,我們的starter也是沒有任何spring依賴,僅僅是我們需要的spring-xxq-test1

  1. 進行測試


    image.png

測試結(jié)果如上辽话,當我們引入上面接入的倆個jar包后肄鸽,啟動該項目就會自動打印出testService初始化這行日志,也就表明我們的配置是成功的油啤。

總結(jié):
上面我們通過了分析spring-boot-starter-redis這個案例典徘,然后我們也仿照寫了一個類似的。通過我們自己的案例村砂,不知道有沒有小伙伴發(fā)現(xiàn)烂斋,我們這種寫法太啰嗦了,完全沒有我一開始的那個demo清晰础废,光是單獨建立一個autoconfigure jar包就感覺毫無意義汛骂。這里確實是很羅嗦,我們的這種寫法评腺,會造成事實上的jar包維護困難帘瞭,而spring之所以能這么做,是因為spring中的sprig-boot-autoconfigure已經(jīng)內(nèi)置在spring框架中蒿讥。因此蝶念,如果我們也這么做,那么我們的xxq-spring-boot-autoconfigure就不應(yīng)該僅僅是為了spring-xxq-test1模塊去服務(wù)芋绸,而是為了我們自己所有的模塊進行自動裝配媒殉,這個一般在企業(yè)級自定義框架中使用比較廣泛。如果是個人創(chuàng)建或者某個中間件的starter摔敛,往往情況是都只有一種功能需要去進行封裝廷蓉,遠沒有企業(yè)級的那么多的框架需求進行封裝。所以我們下面會參考mybatis-spring-boot-starter的案例來進行分析出最恰當?shù)膕tarter應(yīng)該是什么樣的马昙。

在分析mybatis-spring-boot-starter案例之前桃犬,我們先通過一張圖來總結(jié)我們上面的結(jié)論

未命名文件 (1).jpg

內(nèi)置組件指的就是springboot項目內(nèi)置依賴中的一些pom的依賴,而外置依賴就是我們開發(fā)者不斷往springboot項目中加的功能(包括spring提供的以及我們自己添加的)

1.5 分析第三方標準組件

下面我們來深入分析第三方標準組件mybatis-spring-boot-starter行楞,mybatis是一個廣為使用的半orm框架攒暇,因此它和springboot的組件化,一定是能夠代表大部分第三方組件的標準寫法子房。

1.5.1 引入mybatis的pom坐標

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xxq</groupId>
    <artifactId>spring-source-analysis</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.xxq</groupId>
            <artifactId>xxq-spring-boot-autoconfigure</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xxq</groupId>
            <artifactId>xxq-spring-boot-starter-test4</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
      <-- 引入mybatis組件 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
    </dependencies>
</project>

我們使用的是2.1.2版本作為研究版本

1.5.2 分析jar包結(jié)構(gòu)

image.png
image.png

上圖是mybatis-spring-boot-starter的pom文件形用,基于我們上面的總體分析就轧,一般來說xxx-starter依賴中是不含任何代碼的,僅僅是相關(guān)依賴的引入尾序,真正的配置在autoconfigure中钓丰,我們用自己的一張圖來進行說明

mybatis-spring-boot-starter

可以看到mybatis-spring-boot-starter包架構(gòu)整體還是遵循了spring-boot-starter標準模式,但又有其中不太一樣的地方是它將autoconfigure放進了starter中每币,這是和官方唯一不一樣的地方携丁。

上面我們也說了,如果完全按照官方的來進行設(shè)計兰怠,那么整體包維護將變得非常困難梦鉴,業(yè)務(wù)項目工程需要單獨引入autoconfigure和starter倆個包,顯得尤其臃腫揭保,mybatis選擇用自己的方式肥橙,是因為它無法像springboot官方一樣,把autoconfigure包內(nèi)置進spring-boot-autoconfigure中秸侣,以及項目中存筏。所以我們?nèi)绻胍远x第三方starter,可以整體參考mybatis的做法味榛。如下圖所示:

未命名文件 (3).jpg

1.5.3 MybatisAutoConfiguration分析

上面我們借助mybatis-spring-boot-starter分析了標準化的第三方spring-boot-starter應(yīng)該怎么去定義椭坚。接下里我們順便分析下mybatis的自動裝配類是如何工作的


image.png

我們看到這個配置類上有很多注解,我們簡要分析下其中重要幾個注解的作用

  1. Configuration(spring的自動裝配類注解搏色,屬于springframework的注解善茎,在springboot項目中得到廣泛應(yīng)用)
  2. ConditionalOnClass(springboot的條件自動裝配篩選器,配合自動裝配一起使用频轿,classpath路徑下存在某些類垂涯,才會使得當前配置類生效,否則不生效航邢。注意:SqlSessionFactory.class, SqlSessionFactoryBean.class這個是屬于mybatis和mybatis-spring中的耕赘,這也是為什么需要optional依賴這倆個jar包的原因)
  3. ConditionalOnSingleCandidate需要和AutoConfigureAfter一起解釋,首先這倆個都是springboot注解膳殷,說明他是為了自動裝配而服務(wù)的操骡,其次不知道大家還記得上面mybatis-spring-boot-starter結(jié)構(gòu)圖中為何要引入spring-boot-starter-jdbc,就是在此處有用秽之,因為DataSource.class和DataSourceAutoConfiguration.class都是在這個jar包中,因此需要引入依賴吃既,其次ConditionalOnSingleCandidate這個注解主要作用我簡單說明一下:當前spring容器中必須要有DataSource這個bean考榨,而且這個注解一般要結(jié)合AutoConfigureAfter這個注解一起使用,因為如果ConditionalOnSingleCandidate所依賴的bean不是當前配置類初始化鹦倚,你很難保證它在當前配置類之前初始化河质,而AutoConfigureAfter這個配置類就是表示當前配置類在哪個配置類之后進行初始化。

我們可以總結(jié):mybatis肯定是需要依賴DataSource初始化,畢竟它是orm框架掀鹅,存在的前提是需要有數(shù)據(jù)源散休。mybatis使用springboot以及spring注解各種特性來完成和保證mybatis能夠正確成功的初始化

1.6 分析AutoConfigureAfter注解

我們上面分析了springboot-starter官方組件以及第三方標準starter結(jié)構(gòu),對整體自動裝配中的starter模式有了很清晰的認識乐尊,下面我們分析其中一個比較重要的springboot裝配特性AutoConfigureAfter注解

1.6.1 AutoConfigureAfter注解

/*
 * Copyright 2012-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Hint for that an {@link EnableAutoConfiguration auto-configuration} should be applied
 * after other specified auto-configuration classes.
 *
 * @author Phillip Webb
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@Documented
public @interface AutoConfigureAfter {

    /**
     * The auto-configure classes that should have already been applied.
     * @return the classes
     */
    Class<?>[] value() default {};

    /**
     * The names of the auto-configure classes that should have already been applied.
     * @return the class names
     * @since 1.2.2
     */
    String[] name() default {};

}

這個注解內(nèi)容不多戚丸,含義也很明確,就是表示某個自動裝配類在另外一個自動裝配類之后進行應(yīng)用或者初始化扔嵌,注意注釋中有明確說明是EnableAutoConfiguration的自動裝配類限府,不是普通裝配類。

下面我們自己來寫個demo測試一下這個注解

工程1
工程2
工程3

我們建了個三個工程痢缎,工程2在工程1之后初始化胁勺,工程3在工程1之前初始化。我們把這三個jar引入到項目工程中去独旷,看看效果署穗。
運行結(jié)果:

image.png

可以看到,這個注解確實能夠自定義注入的先后順序嵌洼。
但這里有倆個小插曲

1. 6.2 AutoConfigureAfter失效場景

需要注意下案疲,如果不是基于starer模式的這種自動裝配,是不起作用的咱台。

我在當前項目工程中創(chuàng)建了一個類似的配置類络拌,如下:

image.png

理論上來說:這個配置類會先于我引入的其他starter被掃描,因為它在啟動類的classpath下回溺,所以按道理如果不加AutoConfigureAfter春贸,他肯定先于ConfigurationTest1被初始化,然而我現(xiàn)在加上AutoConfigureAfter遗遵,基于這個注解特性萍恕,按道理應(yīng)該晚于ConfigurationTest1被初始化,下面我們看結(jié)果:

image.png

發(fā)現(xiàn)這個注解在這里沒有啟動作用车要,這個原因其實在注解的注釋中寫的很明確了允粤,他只支持EnableAutoConfiguration自動裝配的類,不支持我們這種普通裝配翼岁。

1.6.3 AutoConfigureAfter循環(huán)依賴問題

上面的示例我們分析后类垫,發(fā)現(xiàn)AutoConfigureAfter能夠解決配置類的自定義順序問題,但是如果我們使用不恰當,就會造成不可解決的循環(huán)依賴問題

假設(shè)存在一個工程1脆贵,工程2需要在工程1之后初始化碾褂,我們在工程2上加上AutoConfigureAfter這個注解,然后這時候又來一個工程3售躁,它需要在工程1之前初始化坞淮,我們加上AutoConfigureBefore注解,這時候突然提了個需求陪捷,工程3同時也需要在工程2之后初始化回窘,那么還需要在工程3上加上一個AutoConfigureAfter注解。如下圖所示:
未命名文件 (5).jpg

我們發(fā)現(xiàn)市袖,這成了一個閉環(huán)啡直,spring肯定是無法解決這個循環(huán)依賴的,大家不信的可以自己去試試

寫在最后

這邊留下一個問題凌盯,給大家思考付枫,大家用過spring的應(yīng)該都知道,還有另外一個方法可以控制bean的初始化順序驰怎,這個方法就是@order注解或者Order接口阐滩,這倆個在作用上都是為了自定義初始化順序,那么spring為什么不用這個方式而選擇采用新增一個注解來進行實現(xiàn)呢县忌?

問題將在下篇進行解答掂榔,也歡迎大家在評論區(qū)進行發(fā)言。

本章總結(jié)

由于篇幅有限症杏,同時為了大家觀感體驗装获,自動裝配的第二種方式,就不在本章繼續(xù)進行描述厉颤,轉(zhuǎn)而到下一篇文章進行繼續(xù)描述穴豫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市逼友,隨后出現(xiàn)的幾起案子精肃,更是在濱河造成了極大的恐慌,老刑警劉巖帜乞,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件司抱,死亡現(xiàn)場離奇詭異,居然都是意外死亡黎烈,警方通過查閱死者的電腦和手機习柠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來照棋,“玉大人资溃,你說我怎么就攤上這事×姨浚” “怎么了溶锭?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梳庆。 經(jīng)常有香客問我暖途,道長,這世上最難降的妖魔是什么膏执? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任驻售,我火速辦了婚禮,結(jié)果婚禮上更米,老公的妹妹穿的比我還像新娘欺栗。我一直安慰自己,他們只是感情好征峦,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布迟几。 她就那樣靜靜地躺著,像睡著了一般栏笆。 火紅的嫁衣襯著肌膚如雪类腮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天蛉加,我揣著相機與錄音蚜枢,去河邊找鬼。 笑死针饥,一個胖子當著我的面吹牛厂抽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丁眼,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼筷凤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了苞七?” 一聲冷哼從身側(cè)響起藐守,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎莽鸭,沒想到半個月后吗伤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡硫眨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年足淆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片礁阁。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡巧号,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出姥闭,到底是詐尸還是另有隱情丹鸿,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布棚品,位于F島的核電站靠欢,受9級特大地震影響廊敌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜门怪,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一骡澈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掷空,春花似錦肋殴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酿傍,卻和暖如春烙懦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赤炒。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工修陡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人可霎。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓魄鸦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親癣朗。 傳聞我的和親對象是個殘疾皇子拾因,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

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