Eliminate reserved 'default' profile (SPR-7778)
There is no longer a reserved default profile named 'default'. Rather,
users must explicitly specify a default profile or profiles via
ConfigurableEnvironment.setDefaultProfiles(String...)
- or -
spring.profile.default="pD1,pD2"
Per above, the setDefaultProfile(String) method now accepts a variable
number of profile names (one or more). This is symmetrical with the
existing setActiveProfiles(String...) method.
A typical scenario might involve setting both a default profile as a
servlet context property in web.xml and then setting an active profile
when deploying to production.
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3809 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
d469bf1387
commit
2a4e1c98da
|
|
@ -84,13 +84,13 @@
|
|||
TODO:SPR-7508: Document profile annotation:
|
||||
* may be comma-delimited
|
||||
* empty profile means beans will always be registered
|
||||
* profile="default" means that beans will be registered unless other profile(s) are active
|
||||
* profile="xyz,default" means that beans will be registered if 'xyz' is active or if no profile is active
|
||||
* ConfigurableEnvironment.setDefaultProfileName(String) customizes the name of the default profile
|
||||
* 'spring.profile.default' property customizes the name of the default profile (usually for use as a
|
||||
* ConfigurableEnvironment.setActiveProfiles(String...) sets which profiles are active
|
||||
* 'spring.profile.active' sets which profiles are active (typically as a -D system property)
|
||||
servlet context/init param)
|
||||
* ConfigurableEnvironment.setDefaultProfiles(String...) or 'spring.profile.default' property specifies one
|
||||
or more default profiles, e.g., 'default'
|
||||
* if 'default' is specified as a default profile, `profile="xyz,default"` means that beans will be
|
||||
registered if 'xyz' is active or if no profile is active
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
|
|
|||
|
|
@ -86,21 +86,11 @@ public class ProfileXmlBeanDefinitionTests {
|
|||
|
||||
@Test
|
||||
public void testDefaultProfile() {
|
||||
assertThat(beanFactoryFor(DEFAULT_ELIGIBLE_XML, NONE_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(DEFAULT_ELIGIBLE_XML, "other"), not(containsTargetBean()));
|
||||
|
||||
assertThat(beanFactoryFor(DEFAULT_AND_DEV_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(DEFAULT_AND_DEV_ELIGIBLE_XML, NONE_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(DEFAULT_AND_DEV_ELIGIBLE_XML, PROD_ACTIVE), not(containsTargetBean()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomDefaultProfile() {
|
||||
{
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
ConfigurableEnvironment env = new DefaultEnvironment();
|
||||
env.setDefaultProfile("custom-default");
|
||||
env.setDefaultProfiles("custom-default");
|
||||
reader.setEnvironment(env);
|
||||
reader.loadBeanDefinitions(new ClassPathResource(DEFAULT_ELIGIBLE_XML, getClass()));
|
||||
|
||||
|
|
@ -110,7 +100,7 @@ public class ProfileXmlBeanDefinitionTests {
|
|||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
ConfigurableEnvironment env = new DefaultEnvironment();
|
||||
env.setDefaultProfile("custom-default");
|
||||
env.setDefaultProfiles("custom-default");
|
||||
reader.setEnvironment(env);
|
||||
reader.loadBeanDefinitions(new ClassPathResource(CUSTOM_DEFAULT_ELIGIBLE_XML, getClass()));
|
||||
|
||||
|
|
@ -118,6 +108,44 @@ public class ProfileXmlBeanDefinitionTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultAndNonDefaultProfile() {
|
||||
assertThat(beanFactoryFor(DEFAULT_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(DEFAULT_ELIGIBLE_XML, "other"), not(containsTargetBean()));
|
||||
|
||||
{
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
ConfigurableEnvironment env = new DefaultEnvironment();
|
||||
env.setActiveProfiles(DEV_ACTIVE);
|
||||
env.setDefaultProfiles("default");
|
||||
reader.setEnvironment(env);
|
||||
reader.loadBeanDefinitions(new ClassPathResource(DEFAULT_AND_DEV_ELIGIBLE_XML, getClass()));
|
||||
assertThat(beanFactory, containsTargetBean());
|
||||
}
|
||||
{
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
ConfigurableEnvironment env = new DefaultEnvironment();
|
||||
// env.setActiveProfiles(DEV_ACTIVE);
|
||||
env.setDefaultProfiles("default");
|
||||
reader.setEnvironment(env);
|
||||
reader.loadBeanDefinitions(new ClassPathResource(DEFAULT_AND_DEV_ELIGIBLE_XML, getClass()));
|
||||
assertThat(beanFactory, containsTargetBean());
|
||||
}
|
||||
{
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
ConfigurableEnvironment env = new DefaultEnvironment();
|
||||
// env.setActiveProfiles(DEV_ACTIVE);
|
||||
//env.setDefaultProfiles("default");
|
||||
reader.setEnvironment(env);
|
||||
reader.loadBeanDefinitions(new ClassPathResource(DEFAULT_AND_DEV_ELIGIBLE_XML, getClass()));
|
||||
assertThat(beanFactory, not(containsTargetBean()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private BeanDefinitionRegistry beanFactoryFor(String xmlName, String... activeProfiles) {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
|
|
|
|||
|
|
@ -27,12 +27,13 @@ import java.lang.annotation.Target;
|
|||
* TODO SPR-7508: document
|
||||
*
|
||||
* Components not @Profile-annotated will always be registered
|
||||
* @Profile("default") means that beans will be registered unless other profile(s) are active
|
||||
* @Profile({"xyz,default"}) means that beans will be registered if 'xyz' is active or if no profile is active
|
||||
* ConfigurableEnvironment.setDefaultProfileName(String) customizes the name of the default profile
|
||||
* 'spring.profile.default' property customizes the name of the default profile (usually for use as a servlet context/init param)
|
||||
* ConfigurableEnvironment.setActiveProfiles(String...) sets which profiles are active
|
||||
* 'spring.profile.active' sets which profiles are active (typically as a -D system property)
|
||||
servlet context/init param)
|
||||
* ConfigurableEnvironment.setDefaultProfiles(String...) or 'spring.profile.default' property specifies one
|
||||
or more default profiles, e.g., 'default'
|
||||
* if 'default' is specified as a default profile, @Profile({"xyz,default}) means that beans will be
|
||||
registered if 'xyz' is active or if no profile is active
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -29,7 +29,6 @@ import java.util.regex.Pattern;
|
|||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.core.env.AbstractEnvironment;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.DefaultEnvironment;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
|
|
@ -59,6 +58,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
|||
|
||||
private static final String TEST_BASE_PACKAGE = "example.scannable";
|
||||
private static final String TEST_PROFILE_PACKAGE = "example.profilescan";
|
||||
private static final String TEST_DEFAULT_PROFILE_NAME = "testDefault";
|
||||
|
||||
|
||||
@Test
|
||||
|
|
@ -219,6 +219,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
|||
@Test
|
||||
public void testIntegrationWithAnnotationConfigApplicationContext_defaultProfile() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.getEnvironment().setDefaultProfiles(TEST_DEFAULT_PROFILE_NAME);
|
||||
// no active profiles are set
|
||||
ctx.register(DefaultProfileAnnotatedComponent.class);
|
||||
ctx.refresh();
|
||||
|
|
@ -231,6 +232,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
|||
String beanName = DefaultAndDevProfileAnnotatedComponent.BEAN_NAME;
|
||||
{
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.getEnvironment().setDefaultProfiles(TEST_DEFAULT_PROFILE_NAME);
|
||||
// no active profiles are set
|
||||
ctx.register(beanClass);
|
||||
ctx.refresh();
|
||||
|
|
@ -238,6 +240,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
|||
}
|
||||
{
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.getEnvironment().setDefaultProfiles(TEST_DEFAULT_PROFILE_NAME);
|
||||
ctx.getEnvironment().setActiveProfiles("dev");
|
||||
ctx.register(beanClass);
|
||||
ctx.refresh();
|
||||
|
|
@ -245,6 +248,7 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
|||
}
|
||||
{
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.getEnvironment().setDefaultProfiles(TEST_DEFAULT_PROFILE_NAME);
|
||||
ctx.getEnvironment().setActiveProfiles("other");
|
||||
ctx.register(beanClass);
|
||||
ctx.refresh();
|
||||
|
|
@ -263,13 +267,13 @@ public class ClassPathScanningCandidateComponentProviderTests {
|
|||
}
|
||||
|
||||
|
||||
@Profile(AbstractEnvironment.DEFAULT_PROFILE_NAME)
|
||||
@Profile(TEST_DEFAULT_PROFILE_NAME)
|
||||
@Component(DefaultProfileAnnotatedComponent.BEAN_NAME)
|
||||
private static class DefaultProfileAnnotatedComponent {
|
||||
static final String BEAN_NAME = "defaultProfileAnnotatedComponent";
|
||||
}
|
||||
|
||||
@Profile({AbstractEnvironment.DEFAULT_PROFILE_NAME,"dev"})
|
||||
@Profile({TEST_DEFAULT_PROFILE_NAME,"dev"})
|
||||
@Component(DefaultAndDevProfileAnnotatedComponent.BEAN_NAME)
|
||||
private static class DefaultAndDevProfileAnnotatedComponent {
|
||||
static final String BEAN_NAME = "defaultAndDevProfileAnnotatedComponent";
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.springframework.core.convert.ConversionService;
|
|||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.util.PropertyPlaceholderHelper;
|
||||
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -51,32 +52,23 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
|||
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
||||
|
||||
public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profile.active";
|
||||
|
||||
public static final String DEFAULT_PROFILE_PROPERTY_NAME = "spring.profile.default";
|
||||
|
||||
/**
|
||||
* Default name of the default profile. Override with
|
||||
* {@link #setDefaultProfile(String)}.
|
||||
*
|
||||
* @see #setDefaultProfile(String)
|
||||
*/
|
||||
public static final String DEFAULT_PROFILE_NAME = "default";
|
||||
public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profile.default";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Set<String> activeProfiles = new LinkedHashSet<String>();
|
||||
private Set<String> defaultProfiles = new LinkedHashSet<String>();
|
||||
|
||||
private LinkedList<PropertySource<?>> propertySources = new LinkedList<PropertySource<?>>();
|
||||
private ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||
|
||||
private final PropertyPlaceholderHelper nonStrictHelper =
|
||||
new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, true);
|
||||
|
||||
private final PropertyPlaceholderHelper strictHelper =
|
||||
new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, false);
|
||||
|
||||
private Set<String> activeProfiles = new LinkedHashSet<String>();
|
||||
private LinkedList<PropertySource<?>> propertySources = new LinkedList<PropertySource<?>>();
|
||||
private ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||
|
||||
private boolean explicitlySetProfiles;
|
||||
|
||||
private String defaultProfile = DEFAULT_PROFILE_NAME;
|
||||
|
||||
|
||||
public void addPropertySource(PropertySource<?> propertySource) {
|
||||
|
|
@ -187,28 +179,35 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
|||
}
|
||||
|
||||
public Set<String> getActiveProfiles() {
|
||||
doGetProfiles();
|
||||
if (this.activeProfiles.isEmpty()) {
|
||||
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
|
||||
if (StringUtils.hasText(profiles)) {
|
||||
this.activeProfiles = commaDelimitedListToSet(trimAllWhitespace(profiles));
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(activeProfiles);
|
||||
}
|
||||
|
||||
private void doGetProfiles() {
|
||||
if (explicitlySetProfiles)
|
||||
return;
|
||||
|
||||
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
|
||||
if (profiles == null || profiles.equals("")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeProfiles = commaDelimitedListToSet(trimAllWhitespace(profiles));
|
||||
}
|
||||
|
||||
public void setActiveProfiles(String... profiles) {
|
||||
explicitlySetProfiles = true;
|
||||
this.activeProfiles.clear();
|
||||
this.activeProfiles.addAll(Arrays.asList(profiles));
|
||||
}
|
||||
|
||||
public Set<String> getDefaultProfiles() {
|
||||
if (this.defaultProfiles.isEmpty()) {
|
||||
String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
|
||||
if (StringUtils.hasText(profiles)) {
|
||||
this.defaultProfiles = commaDelimitedListToSet(profiles);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(this.defaultProfiles);
|
||||
}
|
||||
|
||||
public void setDefaultProfiles(String... profiles) {
|
||||
this.defaultProfiles.clear();
|
||||
this.defaultProfiles.addAll(Arrays.asList(profiles));
|
||||
}
|
||||
|
||||
public Map<String, String> getSystemEnvironment() {
|
||||
Map<String,String> systemEnvironment;
|
||||
try {
|
||||
|
|
@ -282,9 +281,10 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
|||
public boolean acceptsProfiles(String[] specifiedProfiles) {
|
||||
boolean activeProfileFound = false;
|
||||
Set<String> activeProfiles = this.getActiveProfiles();
|
||||
Set<String> defaultProfiles = this.getDefaultProfiles();
|
||||
for (String profile : specifiedProfiles) {
|
||||
if (activeProfiles.contains(profile)
|
||||
|| (activeProfiles.isEmpty() && profile.equals(this.getDefaultProfile()))) {
|
||||
|| (activeProfiles.isEmpty() && defaultProfiles.contains(profile))) {
|
||||
activeProfileFound = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -292,18 +292,6 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
|||
return activeProfileFound;
|
||||
}
|
||||
|
||||
public String getDefaultProfile() {
|
||||
String defaultProfileProperty = getProperty(DEFAULT_PROFILE_PROPERTY_NAME);
|
||||
if (defaultProfileProperty != null) {
|
||||
return defaultProfileProperty;
|
||||
}
|
||||
return defaultProfile;
|
||||
}
|
||||
|
||||
public void setDefaultProfile(String defaultProfile) {
|
||||
this.defaultProfile = defaultProfile;
|
||||
}
|
||||
|
||||
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
|
||||
return helper.replacePlaceholders(text, new PlaceholderResolver() {
|
||||
public String resolvePlaceholder(String placeholderName) {
|
||||
|
|
@ -314,8 +302,8 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + " [activeProfiles=" + activeProfiles
|
||||
+ ", propertySources=" + propertySources + "]";
|
||||
return String.format("%s [activeProfiles=%s, defaultProfiles=%s, propertySources=%s]",
|
||||
getClass().getSimpleName(), activeProfiles, defaultProfiles, propertySources);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,10 +30,8 @@ public interface ConfigurableEnvironment extends Environment, PropertySourceAggr
|
|||
void setActiveProfiles(String... profiles);
|
||||
|
||||
/**
|
||||
* Set the default profile name to be used instead of 'default'
|
||||
*
|
||||
* @param defaultProfile
|
||||
* TODO SPR-7508: document
|
||||
*/
|
||||
void setDefaultProfile(String defaultProfile);
|
||||
void setDefaultProfiles(String... profiles);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public interface Environment {
|
|||
/**
|
||||
* TODO SPR-7508: document
|
||||
*/
|
||||
String getDefaultProfile();
|
||||
Set<String> getDefaultProfiles();
|
||||
|
||||
/**
|
||||
* TODO SPR-7508: document
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ import static org.hamcrest.CoreMatchers.notNullValue;
|
|||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.matchers.JUnitMatchers.hasItem;
|
||||
import static org.junit.matchers.JUnitMatchers.hasItems;
|
||||
import static org.springframework.core.env.AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME;
|
||||
import static org.springframework.core.env.AbstractEnvironment.DEFAULT_PROFILE_NAME;
|
||||
import static org.springframework.core.env.AbstractEnvironment.DEFAULT_PROFILE_PROPERTY_NAME;
|
||||
import static org.springframework.core.env.AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME;
|
||||
import static org.springframework.core.env.DefaultEnvironmentTests.CollectionMatchers.isEmpty;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
|
@ -239,26 +239,28 @@ public class DefaultEnvironmentTests {
|
|||
@Test
|
||||
public void systemPropertiesResoloutionOfMultipleProfiles() {
|
||||
assertThat(environment.getActiveProfiles(), isEmpty());
|
||||
|
||||
System.setProperty(ACTIVE_PROFILES_PROPERTY_NAME, "foo,bar");
|
||||
assertThat(environment.getActiveProfiles(), hasItems("foo", "bar"));
|
||||
System.getProperties().remove(ACTIVE_PROFILES_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemPropertiesResolutionOfMulitpleProfiles_withWhitespace() {
|
||||
assertThat(environment.getActiveProfiles(), isEmpty());
|
||||
System.setProperty(ACTIVE_PROFILES_PROPERTY_NAME, " bar , baz "); // notice whitespace
|
||||
assertThat(environment.getActiveProfiles(), not(hasItems("foo", "bar")));
|
||||
assertThat(environment.getActiveProfiles(), hasItems("bar", "baz"));
|
||||
|
||||
System.getProperties().remove(ACTIVE_PROFILES_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentResolutionOfDefaultSpringProfileProperty_noneSet() {
|
||||
assertThat(environment.getDefaultProfile(), equalTo(DEFAULT_PROFILE_NAME));
|
||||
assertThat(environment.getDefaultProfiles(), isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentResolutionOfDefaultSpringProfileProperty_isSet() {
|
||||
testProperties.setProperty(DEFAULT_PROFILE_PROPERTY_NAME, "custom-default");
|
||||
assertThat(environment.getDefaultProfile(), equalTo("custom-default"));
|
||||
testProperties.setProperty(DEFAULT_PROFILES_PROPERTY_NAME, "custom-default");
|
||||
assertTrue(environment.getDefaultProfiles().contains("custom-default"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue