Bean的高級裝配
我們已經(jīng)學(xué)習(xí)了Bean的自動裝配和java顯式裝配,但java的裝配絕不僅限于此。
我們可能會碰到這樣的情況,開發(fā)版本使用H2數(shù)據(jù)庫,為了能達(dá)到開箱即用,向H2數(shù)據(jù)庫中增加了很多測試數(shù)據(jù)。但在生產(chǎn)版本,我們使用的是Oracle數(shù)據(jù)庫,所有的H2配置和數(shù)據(jù)都不應(yīng)該存在。
我們可以提出一種解決方法:兩種配置都寫入配置文件中,在需要的同時(shí)進(jìn)行切換。
問題來了,配置可以寫,但生成DataSource的Bean也不同,不同的Bean類并不能寫入配置文件中。
我們想要這樣的一種裝配功能:我在配置文件中可以聲明使用哪種Bean,哪種Bean就可以生效。
于是,Spring給我們提供了一個Profile的功能,激活!
Profile的功能是怎樣的?
聲明的Profile的Bean類,在Spring運(yùn)行時(shí)會到配置文件中檢測是否有對應(yīng)的Profile激活標(biāo)志,如果有,這個Bean則被激活,可以被創(chuàng)建,否則該Bean不會創(chuàng)建。
例如:
測試使用H2數(shù)據(jù)庫,在創(chuàng)建DataSource上加上注解@Profile("h2-db")
在配置文件中,我們添加上對Profile的激活:
Spring.profiles.active=h2-db
如果沒有profile的激活,對應(yīng)的Bean不會被創(chuàng)建。但一般情況都會有一個默認(rèn)的profile,用actice不太合適吧
是的,我們可以設(shè)置一個默認(rèn)的激活,如果active沒有找到的話,會使用默認(rèn)的激活方式:
Spring.profiles.default
這個profile的激活只能在配置文件中做嗎?
當(dāng)然不是,有多種方式可以設(shè)置這兩個屬性:
- 1.作為DispatcherServlet的初始化參數(shù)
- 2.作為Web應(yīng)用的上下文參數(shù)
- 3.作為JNDI目錄
- 4.作為環(huán)境變量
- 5.作為JVM的系統(tǒng)屬性
- 6.在集成測試上,使用@ActiveProfiles注解設(shè)置
profile在遷移環(huán)境中效果很好,但我現(xiàn)在希望當(dāng)前Bean只要有另一個Bean存在就可以被創(chuàng)建,或者只有在設(shè)置某個特定的環(huán)境變量后才可以被創(chuàng)建,這種需要自己檢測甚至簡單運(yùn)算后才能匹配的條件化配置Bean,使用profile明顯做不到啊。
對應(yīng)這種級別的條件化配置,Spring使用新的注解@Conditional,用到帶有@Bean注解的方法上。如果給定的條件計(jì)算結(jié)果為true,就會創(chuàng)建Bean,否則,Bean被忽略。
@Conditonal如何使用?
例如:當(dāng)前Bean A被創(chuàng)建的條件是Bean B是否存在
- 1.創(chuàng)建A類,并使用@Bean聲明
- 2.創(chuàng)建實(shí)現(xiàn)Condition接口的條件匹配類,并實(shí)現(xiàn)matches方法。
- 3.在matches方法設(shè)置條件的判定:若Bean B的實(shí)例不為null,則返回true,否則返回false
- 4.在使用@Bean的方法上,使用@Conditonal(),在()中放入條件匹配類即可。如果匹配成功,則創(chuàng)建Bean.
條件匹配的類是自己實(shí)現(xiàn)的,所以有無限的可能,幾乎什么樣的條件都可以條件化設(shè)置。甚至可以進(jìn)行進(jìn)一步的封裝,@profile注解就是在@Conditional注解之上來的,在Spring Boot中封裝了很多處理各種條件的條件化配置類,以完成Spring boot的各種自動化裝配