總有那么一些時候,我們希望Spring容器能夠根據我們提供的條件決定哪些Bean需要創建,哪些Bean不需要創建,提供的條件不同,Spring容器創建的Bean也不同,創建的Bean不同,軟體實作的功能自然也有所差別,也就是說,我們希望在某些應用場景下無需修改代碼或重新構建專案,只需簡單修改一下條件就能達到改變軟體功能的目的,
于是,Profile出現了,能讓我們向Spring容器提供一些配置資訊,告訴Spring容器兩件事情:
1.告訴Spring容器我們想要創建的Bean屬于哪個Profile
2.告訴Spring容器只需創建屬于某些Profile的Bean,無需創建屬于其它Profile的Bean
如此一來,Spring容器就能按照指定的Profile創建指定的Bean,指定的Profile不同,創建的Bean也不同,創建的Bean不同,軟體實作的功能自然也就不同,非常明顯,Profile就是專門用來條件化Bean的創建的,
問題在于,我們應該怎樣告訴Spring容器Bean是屬于哪個Profile的呢?
這就涉及@Profile注解了,@Profile注解有個value屬性,能夠指定Bean所屬的Profile,假如com.dream包現有這樣一些類:
1 public interface Music { 2 } 3 4 public class ClassicMusic implements Music { 5 } 6 7 public class CountryMusic implements Music { 8 } 9 10 public class Player { 11 private Music playingMusic = null; 12 13 public Player(Music playingMusic) { 14 this.playingMusic = playingMusic; 15 } 16 }
則可使用@Profile注解這樣配置Bean:
1 @Configuration 2 public class AppConfig { 3 @Bean(name = "classisMusic") 4 @Profile(value = "https://www.cnblogs.com/evanlin/p/classicProfile") 5 public Music produceClassicMusic() { 6 return new ClassicMusic(); 7 } 8 9 @Bean(name = "countryMusic") 10 @Profile(value = "https://www.cnblogs.com/evanlin/p/countryProfile") 11 public Music produceCountryMusic() { 12 return new CountryMusic(); 13 } 14 15 @Bean(name = "player") 16 public Player producePlayer(Music playingMusic) { 17 return new Player(playingMusic); 18 } 19 }
該配置類定義了三個方法,配置了三個Bean:
1.方法produceClassicMusic帶有 @Profile(value = "https://www.cnblogs.com/evanlin/p/classicProfile") 注解,如果激活的是classicProfile,Spring容器就會呼叫這個方法創建ClassicMusic型別的Bean;否則不創建,
2.方法produceCountryMusic帶有 @Profile(value = "https://www.cnblogs.com/evanlin/p/countryProfile") 注解,如果激活的是countryProfile,Spring容器就會呼叫這個方法創建CountryMusic型別的Bean;否則不創建,
3.方法producePlayer沒帶@Profile注解,不屬于任何Profile,不管激活的是哪些Profile,Spring容器都會呼叫這個方法創建Player型別的Bean
于是我們知道了,Bean所屬的Profile是由@Profile注解標注的,接下來我們需要做的,就是告訴Spring容器哪些Profile是激活的,而這,還得仰賴Spring提供的Environment介面,如下所示:
1 try (var context = new AnnotationConfigApplicationContext()) { 2 context.getEnvironment().setActiveProfiles("classicProfile"); 3 context.register(AppConfig.class); 4 context.refresh(); 5 }
這段代碼做了這些事情:
1.創建AnnotationConfigApplicationContext型別的Spring容器,
2.獲取Spring容器里的Environment介面之后呼叫setActiveProfiles方法激活Profile
3.把Java配置類注冊給Spring容器,
4.重繪Spring容器,完成Bean的創建,
毫無疑問,問題的關鍵在于第二步,Environment介面提供了setActiveProfiles方法,用于激活指定的Profile,它的簽名如下:
1 public void setActiveProfiles(String... profiles)
它的引數是 String... 型別的,能夠同時指定多個激活的Profile,而我們的這段代碼只激活了classicProfile,告訴Spring容器只創建ClassicMusic型別的Bean,不創建CountryMusic型別的Bean,當然,Player型別的Bean總會被創建,因為它不屬于任何Profile
值得關注的是,除了激活Profile,我們也能指定默認的Profile,這樣,如果指定了激活的Profile,Spring容器就會使用激活的Profile創建Bean;如果沒有指定激活的Profile,Spring容器就會使用默認的Profile創建Bean,默認的Profile能由Environment介面的setDefaultProfiles方法指定,它的簽名如下:
1 public void setDefaultProfiles(String... profiles)
它的引數是 String... 型別的,同樣支持同時指定多個默認的Profile,這和setActiveProfiles方法是一樣的,不再贅敘,
于是我們知道了,默認或激活的Profile都可呼叫Environment介面指定,而在Web開發中,我們并不需要直接呼叫Environment介面,只要使用spring.profiles.default屬性指定默認的Profile,使用spring.profiles.active屬性指定激活的Profile就行,默認或激活的Profile可以同時指定多個,之間用逗號隔開即可,
這樣,Spring容器就能用spring.profiles.default屬性的值呼叫Environment介面指定默認的Profile;使用pring.profiles.active屬性的值呼叫Environment介面指定激活的Profile,以下是spring.profiles.default屬性和spring.profiles.active屬性可以指定的地方:
1.Servlet初始化引數
2.Servlet背景關系初始化引數
3.JNDI環境變數
4.JVM系統屬性(也就是JVM的命令列引數)
5.作業系統環境變數
比如,我們可在部署描述檔案web.xml里指定Servlet初始化引數和Servlet背景關系初始化引數,這樣指定默認的Profile:
1 <context-param> 2 <param-name>contextConfigLocation</param-name> 3 <param-value>/WEB-INF/config/root-config.xml</param-value> 4 </context-param> 5 <context-param> 6 <param-name>spring.profiles.default</param-name> 7 <param-value>classicProfile</param-value> 8 </context-param> 9 <listener> 10 <listener-class> 11 org.springframework.web.context.ContextLoaderListener 12 </listener-class> 13 </listener> 14 15 <servlet> 16 <servlet-name>dispatcherServlet</servlet-name> 17 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 18 <init-param> 19 <param-name>contextConfigLocation</param-name> 20 <param-value>/WEB-INF/config/servlet-config.xml</param-value> 21 </init-param> 22 <init-param> 23 <param-name>spring.profiles.default</param-name> 24 <param-value>classicProfile</param-value> 25 </init-param> 26 <load-on-startup>1</load-on-startup> 27 </servlet>
在Servlet初始化引數里,我們把classicProfile指給spring.profiles.default屬性,以使根容器知道默認的Profile是classicProfile,進而只創建屬于classicProfile的Bean;在Servlet背景關系初始化引數里,我們把classicProfile指給spring.profiles.default屬性,以使Servlet容器知道默認的Profile是classicProfile,進而只創建屬于classicProfile的Bean
到了運行Web應用程式的時候,如果我們想要創建屬于countryProfile的Bean,只需通過JVM命令列引數之類的,把countryProfile指給spring.profiles.active屬性就行,
還有,@Profile注解除了可以像上面的示例那樣加到配置方法之外,也可以加到配置類上,如下所示:
1 @Configuration 2 @Profile(value = "https://www.cnblogs.com/evanlin/p/classicProfile") 3 public class AppConfigClassic { 4 @Bean(name = "classisMusic") 5 public Music produceClassicMusic() { 6 return new ClassicMusic(); 7 } 8 } 9 10 @Configuration 11 @Profile(value = "https://www.cnblogs.com/evanlin/p/countryProfile") 12 public class AppConfigCountry { 13 @Bean(name = "countryMusic") 14 public Music produceCountryMusic() { 15 return new CountryMusic(); 16 } 17 } 18 19 @Configuration 20 public class AppConfig { 21 @Bean(name = "player") 22 public Player producePlayer(Music playingMusic) { 23 return new Player(playingMusic); 24 } 25 }
這段代碼定義了三個配置類:
1.配置類AppConfigClassic帶有 @Profile(value = "https://www.cnblogs.com/evanlin/p/classicProfile") 注解,只有激活了classicProfile,Spring容器才會創建該配置類里的Bean;否則不創建,
2.配置類AppConfigCountry帶有 @Profile(value = "https://www.cnblogs.com/evanlin/p/countryProfile") 注解,只有激活了countryProfile,Spring容器才會創建該配置類里的Bean;否則不創建,
3.配置類AppConfig沒帶@Profile注解,不管激活了哪些Profile,Spring容器都會創建該配置類里的Bean
當然,XML組態檔也支持Profile,如果采用XML組態檔的話,可用<beans>元素這樣配置:
1 <beans /* 省略命名空間和XSD模式檔案宣告 */> 2 <beans profile="classicProfile"> 3 <bean id="classicMusic" class="com.dream.ClassicMusic"> 4 <property name="musicName" value="Classic Music" /> 5 </bean> 6 </beans> 7 <beans profile="countryProfile"> 8 <bean id="countryMusic" class="com.dream.CountryMusic"> 9 <property name="musicName" value="Country Music" /> 10 </bean> 11 </beans> 12 13 <bean id="player" class="com.dream.Player" autowire="byType" /> 14 </beans>
也可使用多個XML組態檔這樣配置:
1 <beans profile="classicProfile" /* 省略命名空間和XSD模式檔案宣告 */> 2 <bean id="classicMusic" class="com.dream.ClassicMusic"> 3 <property name="musicName" value="Classic Music" /> 4 </bean> 5 </beans> 6 7 <beans profile="countryProfile" /* 省略命名空間和XSD模式檔案宣告 */> 8 <bean id="countryMusic" class="com.dream.CountryMusic"> 9 <property name="musicName" value="Country Music" /> 10 </bean> 11 </beans> 12 13 <beans /* 省略命名空間和XSD模式檔案宣告 */> 14 <bean id="player" class="com.dream.Player" autowire="byType" /> 15 </beans>
至此,關于Profile的介紹也就告一段落了,下章,我們將會開始介紹Condition以及藏在Profile背后的秘密,歡迎大家繼續閱讀,謝謝大家!
回傳目錄 下載代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/451231.html
標籤:Java
上一篇:Nginx
