Profiles
Spring profiles provide a mechanism in the core container that allows for registration of different beans in different environments. In this article, we will go through the profile algorithm and the different ways of using it.The profile attribute is part of beans element. If the beans element doesn't have a profile attribute, then it will always be loaded irrespective of the active profiles set.
If it has a profile, then the active profiles must have at least one of those profile else the beans will not be loaded.
There can be multiple active profiles and multiple profiles in "profile" attribute. The profiles need to be either delimited by space or comma delimited or semi-colon like profile="dev" or profile="dev test" or profile="dev, test" or profile="dev; test".
![]() |
Spring Profiles |
No profiles attribute
testNoProfileAttribute.xml:<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="foo" class="springdemo.Foo"/> </beans>
There is no profile attribute so should work irrespective of the active profiles set.
public void testContextWithNoProfileAttribute() { GenericXmlApplicationContext context = new GenericXmlApplicationContext(); context.getEnvironment().setActiveProfiles("dev"); context.load("springdemo/testNoProfileAttribute.xml"); context.refresh(); assertTrue(context.containsBean("foo")); }
Profile attribute specified in nested beans element
In the below context file, bar has two flavors of implementation depending on the profile.
testProfile.xml:
testProfile.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="foo" class="springdemo.Foo"> <property name="bar" ref="bar"/> </bean> <beans profile="prod"> <bean id="bar" class="springdemo.ProdBar"/> </beans> <beans profile="dev"> <bean id="bar" class="springdemo.DevBar"/> </beans> </beans>
We set the active profiles programatically. If active profile is dev, we get DevBar. If active profile is set to prod, we can ProdBar.
public void testProfileUsingBeansSubElement() {
GenericXmlApplicationContext context = new GenericXmlApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
context.load("springdemo/testProfile.xml");
context.refresh();
assertTrue(context.containsBean("foo"));
Foo foo = (Foo) context.getBean("foo");
assertTrue(foo.getBar() instanceof DevBar);
context = new GenericXmlApplicationContext();
context.getEnvironment().setActiveProfiles("prod");
context.load("springdemo/testProfile.xml");
context.refresh();
assertTrue(context.containsBean("foo"));
foo = (Foo) context.getBean("foo");
assertTrue(foo.getBar() instanceof ProdBar);
// We can also use ClassPathXmlApplicationContext
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext();
appContext.getEnvironment().setActiveProfiles("dev");
appContext.setConfigLocation("springdemo/testProfile.xml");
appContext.refresh();
assertTrue(appContext.containsBean("foo"));
foo = (Foo) appContext.getBean("foo");
assertTrue(foo.getBar() instanceof DevBar);
}
No active profiles set
If the active profiles are not set, then it will result in bean creation failure while trying to create bean definition for "bar".public void testContextWithNoActiveProfiles() { try { GenericXmlApplicationContext context = new GenericXmlApplicationContext(); context.load("springdemo/testProfile.xml"); context.refresh(); } catch (BeanCreationException e) { } }
Profile context decoupled
In the below scenarios, we decouple the profile based implementations into separate context files.The common classes go here:
testProfileCommon.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="foo" class="springdemo.Foo"> <property name="bar" ref="bar"/> </bean> </beans>
Dev based classes go here:
testDevProfile.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <beans profile="dev"> <bean id="bar" class="springdemo.DevBar"/> </beans> </beans>
Prod based classes go here:
testProdProfile.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <beans profile="prod"> <bean id="bar" class="springdemo.ProdBar"/> </beans> </beans>
The active profiles can be set either programatically or using a system property.
Using setter method
public void testProfileUsingSetter() { GenericXmlApplicationContext context = new GenericXmlApplicationContext(); context.getEnvironment().setActiveProfiles("dev"); context.load("springdemo/testProfileCommon.xml", "springdemo/testDevProfile.xml", "springdemo/testProdProfile.xml"); context.refresh(); assertTrue(context.containsBean("foo")); Foo foo = (Foo) context.getBean("foo"); assertTrue(foo.getBar() instanceof DevBar); context = new GenericXmlApplicationContext(); context.getEnvironment().setActiveProfiles("prod"); context.load("springdemo/testProfileCommon.xml", "springdemo/testDevProfile.xml", "springdemo/testProdProfile.xml"); context.refresh(); assertTrue(context.containsBean("foo")); foo = (Foo) context.getBean("foo"); assertTrue(foo.getBar() instanceof ProdBar); }
Using system property
Profiles can be set externally using system property "spring.profiles.active"public void testProfileUsingSystemProperty() { System.setProperty("spring.profiles.active", "dev"); ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext("springdemo/testProfileCommon.xml", "springdemo/testDevProfile.xml", "springdemo/testProdProfile.xml"); Foo foo = (Foo) appContext.getBean("foo"); assertTrue(foo.getBar() instanceof DevBar); System.setProperty("spring.profiles.active", "prod"); appContext = new ClassPathXmlApplicationContext("springdemo/testProfileCommon.xml", "springdemo/testDevProfile.xml", "springdemo/testProdProfile.xml"); foo = (Foo) appContext.getBean("foo"); assertTrue(foo.getBar() instanceof ProdBar); System.setProperty("spring.profiles.active", "dev"); appContext = new ClassPathXmlApplicationContext("springdemo/testProfileCommon.xml", "springdemo/*Profile.xml"); foo = (Foo) appContext.getBean("foo"); assertTrue(foo.getBar() instanceof DevBar); }
Multiple profiles
If we want DevBar to be the implementation used for both dev and test profiles, we can include them in profile attribute as profile="dev,test".testMultiProfile.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="foo" class="springdemo.Foo"> <property name="bar" ref="bar"/> </bean> <beans profile="prod"> <bean id="bar" class="springdemo.ProdBar"/> </beans> <beans profile="dev,test"> <bean id="bar" class="springdemo.DevBar"/> </beans> </beans>In both dev and test profiles, we get the same type of Bar.
public void testMultiProfile() { System.setProperty("spring.profiles.active", "dev"); ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext("springdemo/testMultiProfile.xml"); Foo foo = (Foo) appContext.getBean("foo"); assertTrue(foo.getBar() instanceof DevBar); System.setProperty("spring.profiles.active", "test"); appContext = new ClassPathXmlApplicationContext("springdemo/testMultiProfile.xml"); foo = (Foo) appContext.getBean("foo"); assertTrue(foo.getBar() instanceof DevBar); }
Home
No comments:
Post a Comment