Merge 3.1.0 development branch into trunk

Branch in question is 'env' branch from git://git.springsource.org/sandbox/cbeams.git; merged into
git-svn repository with:

    git merge -s recursive -Xtheirs --no-commit env

No merge conflicts, but did need to

    git rm spring-build

prior to committing.

With this change, Spring 3.1.0 development is now happening on SVN
trunk. Further commits to the 3.0.x line will happen in an as-yet
uncreated SVN branch.  3.1.0 snapshots will be available
per the usual nightly CI build from trunk.
This commit is contained in:
Chris Beams
2010-10-25 19:48:20 +00:00
parent b0ea2b13d2
commit f480333d31
211 changed files with 9876 additions and 623 deletions

View File

@@ -1,44 +1,281 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.config;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ByteArrayResource;
import test.beans.TestBean;
/**
* Tests cornering SPR-7547.
* Unit tests for {@link EnvironmentAwarePropertyPlaceholderConfigurer}.
*
* @see PropertyResourceConfigurerTests
* @author Chris Beams
*/
public class PropertyPlaceholderConfigurerTests {
private static final String P1 = "p1";
private static final String P1_LOCAL_PROPS_VAL = "p1LocalPropsVal";
private static final String P1_SYSTEM_PROPS_VAL = "p1SystemPropsVal";
private static final String P1_SYSTEM_ENV_VAL = "p1SystemEnvVal";
private DefaultListableBeanFactory bf;
private AbstractPropertyPlaceholderConfigurer ppc;
private Properties ppcProperties;
private AbstractBeanDefinition p1BeanDef;
@Before
public void setUp() {
p1BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${"+P1+"}")
.getBeanDefinition();
bf = new DefaultListableBeanFactory();
ppcProperties = new Properties();
ppcProperties.setProperty(P1, P1_LOCAL_PROPS_VAL);
System.setProperty(P1, P1_SYSTEM_PROPS_VAL);
getModifiableSystemEnvironment().put(P1, P1_SYSTEM_ENV_VAL);
ppc = new PropertyPlaceholderConfigurer();
ppc.setProperties(ppcProperties);
}
@After
public void tearDown() {
System.clearProperty(P1);
getModifiableSystemEnvironment().remove(P1);
}
// -------------------------------------------------------------------------
// Tests to ensure backward-compatibility for Environment refactoring
// -------------------------------------------------------------------------
@Test
public void resolveFromSystemProperties() {
getModifiableSystemEnvironment().put("otherKey", "systemValue");
p1BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${"+P1+"}")
.addPropertyValue("sex", "${otherKey}")
.getBeanDefinition();
registerWithGeneratedName(p1BeanDef, bf);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
assertThat(bean.getSex(), equalTo("systemValue"));
getModifiableSystemEnvironment().remove("otherKey");
}
@Test
public void resolveFromLocalProperties() {
tearDown(); // eliminate entries from system props/environment
registerWithGeneratedName(p1BeanDef, bf);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
}
@Test
public void setSystemPropertiesMode_defaultIsFallback() {
registerWithGeneratedName(p1BeanDef, bf);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
}
/*
@Test
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemProperties() {
registerWithGeneratedName(p1BeanDef, bf);
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_SYSTEM_PROPS_VAL));
}
@Test
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemEnvironment() {
registerWithGeneratedName(p1BeanDef, bf);
System.clearProperty(P1); // will now fall all the way back to system environment
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_SYSTEM_ENV_VAL));
}
@Test
public void setSystemSystemPropertiesMode_toOverride_andSetSearchSystemEnvironment_toFalse() {
registerWithGeneratedName(p1BeanDef, bf);
System.clearProperty(P1); // will now fall all the way back to system environment
ppc.setSearchSystemEnvironment(false);
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL)); // has to resort to local props
}
*/
/**
* Prior to the fix for SPR-7547, the following would throw
* IllegalStateException because the PropertiesLoaderSupport base class
* assumed ByteArrayResource implements Resource.getFilename(). It does
* not, and AbstractResource.getFilename() is called instead, raising the
* exception. The following now works, as getFilename() is called in a
* try/catch to check whether the resource is actually file-based or not.
*
* See SPR-7552, which suggests paths to address the root issue rather than
* just patching the problem.
* Creates a scenario in which two PPCs are configured, each with different
* settings regarding resolving properties from the environment.
*/
@Test
public void repro() {
public void twoPlacholderConfigurers_withConflictingSettings() {
String P2 = "p2";
String P2_LOCAL_PROPS_VAL = "p2LocalPropsVal";
String P2_SYSTEM_PROPS_VAL = "p2SystemPropsVal";
String P2_SYSTEM_ENV_VAL = "p2SystemEnvVal";
AbstractBeanDefinition p2BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${"+P1+"}")
.addPropertyValue("country", "${"+P2+"}")
.getBeanDefinition();
bf.registerBeanDefinition("p1Bean", p1BeanDef);
bf.registerBeanDefinition("p2Bean", p2BeanDef);
ppc.setIgnoreUnresolvablePlaceholders(true);
ppc.postProcessBeanFactory(bf);
System.setProperty(P2, P2_SYSTEM_PROPS_VAL);
getModifiableSystemEnvironment().put(P2, P2_SYSTEM_ENV_VAL);
Properties ppc2Properties = new Properties();
ppc2Properties.put(P2, P2_LOCAL_PROPS_VAL);
PropertyPlaceholderConfigurer ppc2 = new PropertyPlaceholderConfigurer();
ppc2.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc2.setProperties(ppc2Properties);
ppc2Properties = new Properties();
ppc2Properties.setProperty(P2, P2_LOCAL_PROPS_VAL);
ppc2.postProcessBeanFactory(bf);
TestBean p1Bean = bf.getBean("p1Bean", TestBean.class);
assertThat(p1Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
TestBean p2Bean = bf.getBean("p2Bean", TestBean.class);
assertThat(p2Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
assertThat(p2Bean.getCountry(), equalTo(P2_SYSTEM_PROPS_VAL));
System.clearProperty(P2);
getModifiableSystemEnvironment().remove(P2);
}
@Test
public void customPlaceholderPrefixAndSuffix() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setPlaceholderPrefix("@<");
ppc.setPlaceholderSuffix(">");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",
rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}").getBeanDefinition());
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocation(new ByteArrayResource("my.name=Inigo Montoya".getBytes()));
ppc.postProcessBeanFactory(bf);
.addPropertyValue("name", "@<key1>")
.addPropertyValue("sex", "${key2}")
.getBeanDefinition());
TestBean testBean = bf.getBean(TestBean.class);
assertThat(testBean.getName(), equalTo("Inigo Montoya"));
System.setProperty("key1", "systemKey1Value");
System.setProperty("key2", "systemKey2Value");
ppc.postProcessBeanFactory(bf);
System.clearProperty("key1");
System.clearProperty("key2");
assertThat(bf.getBean(TestBean.class).getName(), is("systemKey1Value"));
assertThat(bf.getBean(TestBean.class).getSex(), is("${key2}"));
}
@Test
public void nullValueIsPreserved() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setNullValue("customNull");
getModifiableSystemEnvironment().put("my.name", "customNull");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), nullValue());
getModifiableSystemEnvironment().remove("my.name");
}
// -------------------------------------------------------------------------
// Tests for functionality not possible prior to Environment refactoring
// -------------------------------------------------------------------------
/**
* Tests that properties against a BeanFactory's Environment are used by
* PropertyPlaceholderConfigurer during placeholder resolution.
@Test @SuppressWarnings({ "unchecked", "rawtypes", "serial" })
public void replacePlaceholdersFromBeanFactoryEnvironmentPropertySources() {
System.setProperty("key1", "systemValue");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.getEnvironment().addPropertySource("psCustom", new HashMap() {{ put("key1", "customValue"); }});
bf.registerBeanDefinition("testBean",
rootBeanDefinition(TestBean.class).addPropertyValue("name", "${key1}").getBeanDefinition());
new PropertyPlaceholderConfigurer().postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), is("customValue"));
System.clearProperty("key1");
}
*/
// -------------------------------------------------------------------------
// Utilities
// -------------------------------------------------------------------------
// TODO SPR-7508: duplicated from EnvironmentPropertyResolutionSearchTests
@SuppressWarnings("unchecked")
private static Map<String, String> getModifiableSystemEnvironment() {
Class<?>[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for (Class<?> cl : classes) {
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
try {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
return (Map<String, String>) obj;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
throw new IllegalStateException();
}
}

View File

@@ -16,6 +16,14 @@
package org.springframework.beans.factory.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
import static test.util.TestResourceUtils.qualifiedResource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -23,18 +31,12 @@ import java.util.Properties;
import java.util.Set;
import java.util.prefs.Preferences;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import test.beans.IndexedTestBean;
import test.beans.TestBean;
import static test.util.TestResourceUtils.*;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.ManagedList;
@@ -43,11 +45,15 @@ import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.io.Resource;
import test.beans.IndexedTestBean;
import test.beans.TestBean;
/**
* Unit tests for various {@link PropertyResourceConfigurer} implementations including:
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
* {@link PreferencesPlaceholderConfigurer}.
*
* @see PropertyPlaceholderConfigurerTests
* @since 02.10.2003
* @author Juergen Hoeller
* @author Chris Beams
@@ -794,6 +800,39 @@ public final class PropertyResourceConfigurerTests {
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
}
/* TODO SPR-7508: uncomment after EnvironmentAwarePropertyPlaceholderConfigurer implementation
@Test
public void testPreferencesPlaceholderConfigurerWithCustomPropertiesInEnvironment() {
factory.registerBeanDefinition("tb",
genericBeanDefinition(TestBean.class)
.addPropertyValue("name", "${mypath/myName}")
.addPropertyValue("age", "${myAge}")
.addPropertyValue("touchy", "${myotherpath/myTouchy}")
.getBeanDefinition());
Properties props = new Properties();
props.put("myAge", "99");
factory.getEnvironment().getPropertySources().add(new PropertiesPropertySource("localProps", props));
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
ppc.setSystemTreePath("mySystemPath");
ppc.setUserTreePath("myUserPath");
Preferences.systemRoot().node("mySystemPath").node("mypath").put("myName", "myNameValue");
Preferences.systemRoot().node("mySystemPath/myotherpath").put("myTouchy", "myTouchyValue");
Preferences.userRoot().node("myUserPath/myotherpath").put("myTouchy", "myOtherTouchyValue");
ppc.afterPropertiesSet();
ppc.postProcessBeanFactory(factory);
TestBean tb = (TestBean) factory.getBean("tb");
assertEquals("myNameValue", tb.getName());
assertEquals(99, tb.getAge());
assertEquals("myOtherTouchyValue", tb.getTouchy());
Preferences.userRoot().node("myUserPath/myotherpath").remove("myTouchy");
Preferences.systemRoot().node("mySystemPath/myotherpath").remove("myTouchy");
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
}
*/
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<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="testBean" class="test.beans.TestBean">
<property name="name" value="topLevel"/>
</bean>
<beans>
<bean id="testBean" class="test.beans.TestBean">
<property name="name" value="nested"/>
</bean>
</beans>
</beans>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<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="testBean" class="test.beans.TestBean">
<property name="name" value="original"/>
</bean>
<!-- STS should raise an error for this duplicate id -->
<bean id="testBean" class="test.beans.TestBean">
<property name="name" value="duplicate"/>
</bean>
</beans>

View File

@@ -0,0 +1,66 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ClassPathResource;
import test.beans.TestBean;
/**
* With Spring 3.1, bean id attributes (and all other id attributes across the
* core schemas) are no longer typed as xsd:id, but as xsd:string. This allows
* for using the same bean id within nested <beans> elements.
*
* Duplicate ids *within the same level of nesting* will still be treated as an
* error through the ProblemReporter, as this could never be an intended/valid
* situation.
*
* @author Chris Beams
* @since 3.1
* @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateName
* @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateNameInAlias
*/
public class DuplicateBeanIdTests {
@Test
public void duplicateBeanIdsWithinSameNestingLevelRaisesError() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
try {
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-sameLevel-context.xml", this.getClass()));
fail("expected parsing exception due to duplicate ids in same nesting level");
} catch (Exception ex) {
// expected
}
}
@Test
public void duplicateBeanIdsAcrossNestingLevels() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-multiLevel-context.xml", this.getClass()));
TestBean testBean = bf.getBean(TestBean.class); // there should be only one
assertThat(testBean.getName(), equalTo("nested"));
}
}

View File

@@ -0,0 +1,113 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.internal.matchers.TypeSafeMatcher;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.io.ClassPathResource;
/**
* TODO SPR-7508: document
*
* @author Chris Beams
*/
public class EnvironmentBeansTests {
private static final String PROD_ELIGIBLE_XML = "environmentBeans-prodProfile.xml";
private static final String DEV_ELIGIBLE_XML = "environmentBeans-devProfile.xml";
private static final String ALL_ELIGIBLE_XML = "environmentBeans-noProfile.xml";
private static final String MULTI_ELIGIBLE_XML = "environmentBeans-multiProfile.xml";
private static final String UNKOWN_ELIGIBLE_XML = "environmentBeans-unknownProfile.xml";
private static final String PROD_ACTIVE = "prod";
private static final String DEV_ACTIVE = "dev";
private static final String NULL_ACTIVE = null;
private static final String UNKNOWN_ACTIVE = "unknown";
private static final String[] NONE_ACTIVE = new String[0];
private static final String[] MULTI_ACTIVE = new String[] { PROD_ACTIVE, DEV_ACTIVE };
private static final String TARGET_BEAN = "foo";
@Test
public void test() {
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, DEV_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, PROD_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NONE_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NULL_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, UNKNOWN_ACTIVE), not(containsTargetBean()));
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
assertThat(beanFactoryFor(UNKOWN_ELIGIBLE_XML, MULTI_ACTIVE), not(containsTargetBean()));
}
private BeanDefinitionRegistry beanFactoryFor(String xmlName, String... activeProfileNames) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
DefaultEnvironment env = new DefaultEnvironment();
env.setActiveProfiles(activeProfileNames);
reader.setEnvironment(env);
reader.loadBeanDefinitions(new ClassPathResource(xmlName, getClass()));
return beanFactory;
}
private static Matcher<BeanDefinitionRegistry> containsBeanDefinition(final String beanName) {
return new TypeSafeMatcher<BeanDefinitionRegistry>() {
public void describeTo(Description desc) {
desc.appendText("a BeanDefinitionRegistry containing bean named ")
.appendValue(beanName);
}
@Override
public boolean matchesSafely(BeanDefinitionRegistry beanFactory) {
return beanFactory.containsBeanDefinition(beanName);
}
};
}
private static Matcher<BeanDefinitionRegistry> containsTargetBean() {
return containsBeanDefinition(TARGET_BEAN);
}
}

View File

@@ -0,0 +1,148 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ClassPathResource;
import test.beans.TestBean;
/**
* Tests for propagating enclosing beans element defaults to nested beans elements.
*
* @author Chris Beams
*/
public class NestedBeansElementAttributeRecursionTests {
@Test
public void defaultLazyInit() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-lazy-context.xml", this.getClass()));
BeanDefinition foo = bf.getBeanDefinition("foo");
BeanDefinition bar = bf.getBeanDefinition("bar");
BeanDefinition baz = bf.getBeanDefinition("baz");
BeanDefinition biz = bf.getBeanDefinition("biz");
BeanDefinition buz = bf.getBeanDefinition("buz");
assertThat(foo.isLazyInit(), is(false));
assertThat(bar.isLazyInit(), is(true));
assertThat(baz.isLazyInit(), is(false));
assertThat(biz.isLazyInit(), is(true));
assertThat(buz.isLazyInit(), is(true));
}
@Test
@SuppressWarnings("unchecked")
public void defaultMerge() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-merge-context.xml", this.getClass()));
TestBean topLevel = bf.getBean("topLevelConcreteTestBean", TestBean.class);
// has the concrete child bean values
assertThat(topLevel.getSomeList(), hasItems("charlie", "delta"));
// but does not merge the parent values
assertThat(topLevel.getSomeList(), not(hasItems("alpha", "bravo")));
TestBean firstLevel = bf.getBean("firstLevelNestedTestBean", TestBean.class);
// merges all values
assertThat(firstLevel.getSomeList(),
hasItems("charlie", "delta", "echo", "foxtrot"));
TestBean secondLevel = bf.getBean("secondLevelNestedTestBean", TestBean.class);
// merges all values
assertThat(secondLevel.getSomeList(),
hasItems("charlie", "delta", "echo", "foxtrot", "golf", "hotel"));
}
@Test
public void defaultAutowireCandidates() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-autowire-candidates-context.xml", this.getClass()));
assertThat(bf.getBeanDefinition("fooService").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("fooRepository").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("other").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("barService").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("fooController").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("bizRepository").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("bizService").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("bazService").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("random").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("fooComponent").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("fRepository").isAutowireCandidate(), is(false));
assertThat(bf.getBeanDefinition("aComponent").isAutowireCandidate(), is(true));
assertThat(bf.getBeanDefinition("someService").isAutowireCandidate(), is(false));
}
@Test
public void initMethod() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
new ClassPathResource("NestedBeansElementAttributeRecursionTests-init-destroy-context.xml", this.getClass()));
InitDestroyBean beanA = bf.getBean("beanA", InitDestroyBean.class);
InitDestroyBean beanB = bf.getBean("beanB", InitDestroyBean.class);
InitDestroyBean beanC = bf.getBean("beanC", InitDestroyBean.class);
InitDestroyBean beanD = bf.getBean("beanD", InitDestroyBean.class);
assertThat(beanA.initMethod1Called, is(true));
assertThat(beanB.initMethod2Called, is(true));
assertThat(beanC.initMethod3Called, is(true));
assertThat(beanD.initMethod2Called, is(true));
bf.destroySingletons();
assertThat(beanA.destroyMethod1Called, is(true));
assertThat(beanB.destroyMethod2Called, is(true));
assertThat(beanC.destroyMethod3Called, is(true));
assertThat(beanD.destroyMethod2Called, is(true));
}
}
class InitDestroyBean {
boolean initMethod1Called;
boolean initMethod2Called;
boolean initMethod3Called;
boolean destroyMethod1Called;
boolean destroyMethod2Called;
boolean destroyMethod3Called;
void initMethod1() { this.initMethod1Called = true; }
void initMethod2() { this.initMethod2Called = true; }
void initMethod3() { this.initMethod3Called = true; }
void destroyMethod1() { this.destroyMethod1Called = true; }
void destroyMethod2() { this.destroyMethod2Called = true; }
void destroyMethod3() { this.destroyMethod3Called = true; }
}

View File

@@ -0,0 +1,49 @@
package org.springframework.beans.factory.xml;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
* Tests for new nested beans element support in Spring XML
*
* @author Chris Beams
*/
public class NestedBeansElementTests {
private final Resource XML =
new ClassPathResource("NestedBeansElementTests-context.xml", this.getClass());
@Test
public void getBean_withoutActiveProfile() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(XML);
Object foo = bf.getBean("foo");
assertThat(foo, instanceOf(String.class));
}
@Test
public void getBean_withActiveProfile() {
ConfigurableEnvironment env = new DefaultEnvironment();
env.setActiveProfiles("dev");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.setEnvironment(env);
reader.loadBeanDefinitions(XML);
bf.getBean("devOnlyBean"); // should not throw NSBDE
Object foo = bf.getBean("foo");
assertThat(foo, instanceOf(Integer.class));
bf.getBean("devOnlyBean");
}
}