profilelist被全部删除 Profile

总有那么一些时候,我们希望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 } 34 public class ClassicMusic implements Music { 5 } 67 public class CountryMusic implements Music { 8 } 9 10 public class Player {11private Music playingMusic = null;12 13public Player(Music playingMusic) {14this.playingMusic = playingMusic;15}16 }则可使用@Profile注解这样配置Bean:
1 @Configuration 2 public class AppConfig { 3@Bean(name = "classisMusic") 4@Profile(value = "https://tazarkount.com/read/classicProfile") 5public Music produceClassicMusic() { 6return new ClassicMusic(); 7} 89@Bean(name = "countryMusic")10@Profile(value = "https://tazarkount.com/read/countryProfile")11public Music produceCountryMusic() {12return new CountryMusic();13}14 15@Bean(name = "player")16public Player producePlayer(Music playingMusic) {17return new Player(playingMusic);18}19 } 该配置类定义了三个方法,配置了三个Bean:
1.方法produceClassicMusic带有 @Profile(value = "https://tazarkount.com/read/classicProfile") 注解 。如果激活的是classicProfile,Spring容器就会调用这个方法创建ClassicMusic类型的Bean;否则不创建 。
2.方法produceCountryMusic带有 @Profile(value = "https://tazarkount.com/read/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()) {2context.getEnvironment().setActiveProfiles("classicProfile");3context.register(AppConfig.class);4context.refresh();5 } 这段代码做了这些事情:
1.创建AnnotationConfigApplicationContext类型的Spring容器 。
2.获取Spring容器里的Environment接口之后调用setActiveProfiles方法激活Profile
3.把Java配置类注册给Spring容器 。
4.刷新Spring容器,完成Bean的创建 。
毫无疑问,问题的关键在于第二步 。Environment接口提供了setActiveProfiles方法,用于激活指定的Profile 。它的签名如下:
【profilelist被全部删除 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>11org.springframework.web.context.ContextLoaderListener12</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://tazarkount.com/read/classicProfile") 3 public class AppConfigClassic { 4@Bean(name = "classisMusic") 5public Music produceClassicMusic() { 6return new ClassicMusic(); 7} 8 } 9 10 @Configuration11 @Profile(value = "https://tazarkount.com/read/countryProfile")12 public class AppConfigCountry {13@Bean(name = "countryMusic")14public Music produceCountryMusic() {15return new CountryMusic();16}17 }18 19 @Configuration20 public class AppConfig {21@Bean(name = "player")22public Player producePlayer(Music playingMusic) {23return new Player(playingMusic);24}25 } 这段代码定义了三个配置类:
1.配置类AppConfigClassic带有 @Profile(value = "https://tazarkount.com/read/classicProfile") 注解 。只有激活了classicProfile,Spring容器才会创建该配置类里的Bean;否则不创建 。
2.配置类AppConfigCountry带有 @Profile(value = "https://tazarkount.com/read/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="https://tazarkount.com/read/Classic Music" /> 5</bean> 6</beans> 7<beans profile="countryProfile"> 8<bean id="countryMusic" class="com.dream.CountryMusic"> 9<property name="musicName" value="https://tazarkount.com/read/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="https://tazarkount.com/read/Classic Music" /> 4</bean> 5 </beans> 67 <beans profile="countryProfile" /* 省略命名空间和XSD模式文件声明 */> 8<bean id="countryMusic" class="com.dream.CountryMusic"> 9<property name="musicName" value="https://tazarkount.com/read/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背后的秘密 。欢迎大家继续阅读,谢谢大家!
返回目录    下载代码