Additional configuration classes get detected when imported through XML or registrars

Issue: SPR-11430
Issue: SPR-11723
This commit is contained in:
Juergen Hoeller 2014-08-12 17:23:21 +02:00
parent f1f1c4c980
commit 71c6eb2bb5
5 changed files with 182 additions and 112 deletions

View File

@ -113,6 +113,8 @@ class ConfigurationClassParser {
private final ComponentScanAnnotationParser componentScanParser; private final ComponentScanAnnotationParser componentScanParser;
private final ConditionEvaluator conditionEvaluator;
private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = private final Map<ConfigurationClass, ConfigurationClass> configurationClasses =
new LinkedHashMap<ConfigurationClass, ConfigurationClass>(); new LinkedHashMap<ConfigurationClass, ConfigurationClass>();
@ -125,8 +127,6 @@ class ConfigurationClassParser {
private final List<DeferredImportSelectorHolder> deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>(); private final List<DeferredImportSelectorHolder> deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
private final ConditionEvaluator conditionEvaluator;
/** /**
* Create a new {@link ConfigurationClassParser} instance that will be used * Create a new {@link ConfigurationClassParser} instance that will be used
@ -488,6 +488,10 @@ class ConfigurationClassParser {
return this.configurationClasses.keySet(); return this.configurationClasses.keySet();
} }
public int getPropertySourceCount() {
return this.propertySources.size();
}
public List<PropertySource<?>> getPropertySources() { public List<PropertySource<?>> getPropertySources() {
List<PropertySource<?>> propertySources = new LinkedList<PropertySource<?>>(); List<PropertySource<?>> propertySources = new LinkedList<PropertySource<?>>();
for (Map.Entry<String, List<ResourcePropertySource>> entry : this.propertySources.entrySet()) { for (Map.Entry<String, List<ResourcePropertySource>> entry : this.propertySources.entrySet()) {

View File

@ -17,6 +17,7 @@
package org.springframework.context.annotation; package org.springframework.context.annotation;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -269,7 +270,9 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
*/ */
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
Set<BeanDefinitionHolder> configCandidates = new LinkedHashSet<BeanDefinitionHolder>(); Set<BeanDefinitionHolder> configCandidates = new LinkedHashSet<BeanDefinitionHolder>();
for (String beanName : registry.getBeanDefinitionNames()) { String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName); BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
@ -302,32 +305,59 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
ConfigurationClassParser parser = new ConfigurationClassParser( ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment, this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry); this.resourceLoader, this.componentScanBeanNameGenerator, registry);
parser.parse(configCandidates);
parser.validate();
// Handle any @PropertySource annotations Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
List<PropertySource<?>> parsedPropertySources = parser.getPropertySources(); int propertySourceCount = 0;
if (!parsedPropertySources.isEmpty()) { do {
if (!(this.environment instanceof ConfigurableEnvironment)) { parser.parse(configCandidates);
logger.warn("Ignoring @PropertySource annotations. " + parser.validate();
"Reason: Environment must implement ConfigurableEnvironment");
} // Handle any @PropertySource annotations
else { if (parser.getPropertySourceCount() > propertySourceCount) {
MutablePropertySources envPropertySources = ((ConfigurableEnvironment) this.environment).getPropertySources(); List<PropertySource<?>> parsedPropertySources = parser.getPropertySources();
for (PropertySource<?> propertySource : parsedPropertySources) { if (!parsedPropertySources.isEmpty()) {
envPropertySources.addLast(propertySource); if (!(this.environment instanceof ConfigurableEnvironment)) {
logger.warn("Ignoring @PropertySource annotations. " +
"Reason: Environment must implement ConfigurableEnvironment");
}
else {
MutablePropertySources envPropertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
for (PropertySource<?> propertySource : parsedPropertySources) {
envPropertySources.addLast(propertySource);
}
}
} }
propertySourceCount = parser.getPropertySourceCount();
}
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor,
this.problemReporter, this.metadataReaderFactory, this.resourceLoader, this.environment,
this.importBeanNameGenerator);
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
configCandidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition beanDef = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, candidateName));
}
}
}
candidateNames = newCandidateNames;
} }
} }
while (!configCandidates.isEmpty());
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor,
this.problemReporter, this.metadataReaderFactory, this.resourceLoader, this.environment,
this.importBeanNameGenerator);
}
this.reader.loadBeanDefinitions(parser.getConfigurationClasses());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (singletonRegistry != null) { if (singletonRegistry != null) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,10 +22,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.GenericBeanDefinition;
@ -42,6 +41,7 @@ import static org.junit.Assert.*;
* annotation metadata of the @Configuration class that imported it. * annotation metadata of the @Configuration class that imported it.
* *
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller
* @since 3.1 * @since 3.1
*/ */
public class ImportAwareTests { public class ImportAwareTests {
@ -51,8 +51,7 @@ public class ImportAwareTests {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ImportingConfig.class); ctx.register(ImportingConfig.class);
ctx.refresh(); ctx.refresh();
assertNotNull(ctx.getBean("importedConfigBean"));
ctx.getBean("importedConfigBean");
ImportedConfig importAwareConfig = ctx.getBean(ImportedConfig.class); ImportedConfig importAwareConfig = ctx.getBean(ImportedConfig.class);
AnnotationMetadata importMetadata = importAwareConfig.importMetadata; AnnotationMetadata importMetadata = importAwareConfig.importMetadata;
@ -68,8 +67,7 @@ public class ImportAwareTests {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(IndirectlyImportingConfig.class); ctx.register(IndirectlyImportingConfig.class);
ctx.refresh(); ctx.refresh();
assertNotNull(ctx.getBean("importedConfigBean"));
ctx.getBean("importedConfigBean");
ImportedConfig importAwareConfig = ctx.getBean(ImportedConfig.class); ImportedConfig importAwareConfig = ctx.getBean(ImportedConfig.class);
AnnotationMetadata importMetadata = importAwareConfig.importMetadata; AnnotationMetadata importMetadata = importAwareConfig.importMetadata;
@ -87,6 +85,7 @@ public class ImportAwareTests {
ctx.register(ImportingRegistrarConfig.class); ctx.register(ImportingRegistrarConfig.class);
ctx.refresh(); ctx.refresh();
assertNotNull(ctx.getBean("registrarImportedBean")); assertNotNull(ctx.getBean("registrarImportedBean"));
assertNotNull(ctx.getBean("otherImportedConfigBean"));
} }
@Test @Test
@ -96,9 +95,12 @@ public class ImportAwareTests {
ctx.register(ImportingRegistrarConfigWithImport.class); ctx.register(ImportingRegistrarConfigWithImport.class);
ctx.refresh(); ctx.refresh();
assertNotNull(ctx.getBean("registrarImportedBean")); assertNotNull(ctx.getBean("registrarImportedBean"));
assertNotNull(ctx.getBean("otherImportedConfigBean"));
assertNotNull(ctx.getBean("importedConfigBean"));
assertNotNull(ctx.getBean(ImportedConfig.class)); assertNotNull(ctx.getBean(ImportedConfig.class));
} }
@Configuration @Configuration
@Import(ImportedConfig.class) @Import(ImportedConfig.class)
static class ImportingConfig { static class ImportingConfig {
@ -140,28 +142,40 @@ public class ImportAwareTests {
} }
@Configuration
static class OtherImportedConfig {
@Bean
public String otherImportedConfigBean() {
return "";
}
}
static class BPP implements BeanFactoryAware, BeanPostProcessor { static class BPP implements BeanFactoryAware, BeanPostProcessor {
@Override @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean; return bean;
} }
@Override @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean; return bean;
} }
@Override @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { public void setBeanFactory(BeanFactory beanFactory) {
} }
} }
@Configuration @Configuration
@EnableImportRegistrar @EnableImportRegistrar
static class ImportingRegistrarConfig { static class ImportingRegistrarConfig {
} }
@Configuration @Configuration
@EnableImportRegistrar @EnableImportRegistrar
@Import(ImportedConfig.class) @Import(ImportedConfig.class)
@ -174,18 +188,22 @@ public class ImportAwareTests {
public @interface EnableImportRegistrar { public @interface EnableImportRegistrar {
} }
static class ImportedRegistrar implements ImportBeanDefinitionRegistrar { static class ImportedRegistrar implements ImportBeanDefinitionRegistrar {
static boolean called; static boolean called;
@Override @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinitionRegistry registry) { GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName(String.class.getName()); beanDefinition.setBeanClassName(String.class.getName());
registry.registerBeanDefinition("registrarImportedBean", beanDefinition ); registry.registerBeanDefinition("registrarImportedBean", beanDefinition);
Assert.state(called == false, "ImportedRegistrar called twice"); GenericBeanDefinition beanDefinition2 = new GenericBeanDefinition();
beanDefinition2.setBeanClass(OtherImportedConfig.class);
registry.registerBeanDefinition("registrarImportedConfig", beanDefinition2);
Assert.state(!called, "ImportedRegistrar called twice");
called = true; called = true;
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,13 +20,9 @@ import java.util.Collections;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Before;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.aop.support.AopUtils; import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -39,6 +35,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.ImportResource;
import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.tests.sample.beans.TestBean;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
/** /**
* Integration tests for {@link ImportResource} support. * Integration tests for {@link ImportResource} support.
@ -47,6 +47,7 @@ import org.springframework.core.env.PropertySource;
* @author Juergen Hoeller * @author Juergen Hoeller
*/ */
public class ImportResourceTests { public class ImportResourceTests {
@Test @Test
public void testImportXml() { public void testImportXml() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlConfig.class); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlConfig.class);
@ -56,16 +57,6 @@ public class ImportResourceTests {
assertEquals("myName", tb.getName()); assertEquals("myName", tb.getName());
} }
@Configuration
@ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml")
static class ImportXmlConfig {
@Value("${name}")
private String name;
public @Bean TestBean javaDeclaredBean() {
return new TestBean(this.name);
}
}
@Ignore // TODO: SPR-6310 @Ignore // TODO: SPR-6310
@Test @Test
public void testImportXmlWithRelativePath() { public void testImportXmlWithRelativePath() {
@ -76,14 +67,6 @@ public class ImportResourceTests {
assertEquals("myName", tb.getName()); assertEquals("myName", tb.getName());
} }
@Configuration
@ImportResource("ImportXmlConfig-context.xml")
static class ImportXmlWithRelativePathConfig {
public @Bean TestBean javaDeclaredBean() {
return new TestBean("java.declared");
}
}
@Ignore // TODO: SPR-6310 @Ignore // TODO: SPR-6310
@Test @Test
public void testImportXmlByConvention() { public void testImportXmlByConvention() {
@ -91,11 +74,6 @@ public class ImportResourceTests {
assertTrue("context does not contain xml-declared bean", ctx.containsBean("xmlDeclaredBean")); assertTrue("context does not contain xml-declared bean", ctx.containsBean("xmlDeclaredBean"));
} }
@Configuration
//@ImportXml
static class ImportXmlByConventionConfig {
}
@Test @Test
public void testImportXmlIsInheritedFromSuperclassDeclarations() { public void testImportXmlIsInheritedFromSuperclassDeclarations() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(FirstLevelSubConfig.class); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(FirstLevelSubConfig.class);
@ -109,6 +87,78 @@ public class ImportResourceTests {
assertTrue("failed to pick up parent-declared XML bean", ctx.containsBean("xmlDeclaredBean")); assertTrue("failed to pick up parent-declared XML bean", ctx.containsBean("xmlDeclaredBean"));
} }
@Test
public void testImportXmlWithNamespaceConfig() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlWithAopNamespaceConfig.class);
Object bean = ctx.getBean("proxiedXmlBean");
assertTrue(AopUtils.isAopProxy(bean));
}
@Test
public void testImportXmlWithOtherConfigurationClass() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlWithConfigurationClass.class);
assertTrue("did not contain java-declared bean", ctx.containsBean("javaDeclaredBean"));
assertTrue("did not contain xml-declared bean", ctx.containsBean("xmlDeclaredBean"));
TestBean tb = ctx.getBean("javaDeclaredBean", TestBean.class);
assertEquals("myName", tb.getName());
}
@Ignore // TODO: SPR-6327
@Test
public void testImportDifferentResourceTypes() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SubResourceConfig.class);
assertTrue(ctx.containsBean("propertiesDeclaredBean"));
assertTrue(ctx.containsBean("xmlDeclaredBean"));
}
@Test
public void importWithPlaceholder() throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
PropertySource<?> propertySource = new MapPropertySource("test",
Collections.<String, Object> singletonMap("test", "springframework"));
ctx.getEnvironment().getPropertySources().addFirst(propertySource);
ctx.register(ImportXmlConfig.class);
ctx.refresh();
assertTrue("did not contain xml-declared bean", ctx.containsBean("xmlDeclaredBean"));
}
@Test
public void testImportXmlWithAutowiredConfig() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlAutowiredConfig.class);
String name = ctx.getBean("xmlBeanName", String.class);
assertThat(name, equalTo("xml.declared"));
}
@Test
public void testImportNonXmlResource() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportNonXmlResourceConfig.class);
assertTrue(ctx.containsBean("propertiesDeclaredBean"));
}
@Configuration
@ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml")
static class ImportXmlConfig {
@Value("${name}")
private String name;
public @Bean TestBean javaDeclaredBean() {
return new TestBean(this.name);
}
}
@Configuration
@ImportResource("ImportXmlConfig-context.xml")
static class ImportXmlWithRelativePathConfig {
public @Bean TestBean javaDeclaredBean() {
return new TestBean("java.declared");
}
}
@Configuration
//@ImportXml
static class ImportXmlByConventionConfig {
}
@Configuration @Configuration
@ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml") @ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml")
static class BaseConfig { static class BaseConfig {
@ -123,13 +173,6 @@ public class ImportResourceTests {
static class SecondLevelSubConfig extends BaseConfig { static class SecondLevelSubConfig extends BaseConfig {
} }
@Test
public void testImportXmlWithNamespaceConfig() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlWithAopNamespaceConfig.class);
Object bean = ctx.getBean("proxiedXmlBean");
assertTrue(AopUtils.isAopProxy(bean));
}
@Configuration @Configuration
@ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlWithAopNamespace-context.xml") @ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlWithAopNamespace-context.xml")
static class ImportXmlWithAopNamespaceConfig { static class ImportXmlWithAopNamespaceConfig {
@ -141,11 +184,9 @@ public class ImportResourceTests {
public void advice() { } public void advice() { }
} }
@Test @Configuration
public void testImportXmlWithAutowiredConfig() { @ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlWithConfigurationClass-context.xml")
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlAutowiredConfig.class); static class ImportXmlWithConfigurationClass {
String name = ctx.getBean("xmlBeanName", String.class);
assertThat(name, equalTo("xml.declared"));
} }
@Configuration @Configuration
@ -158,47 +199,16 @@ public class ImportResourceTests {
} }
} }
@Test
public void testImportNonXmlResource() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportNonXmlResourceConfig.class);
assertTrue(ctx.containsBean("propertiesDeclaredBean"));
}
@Configuration @Configuration
@ImportResource(value="classpath:org/springframework/context/annotation/configuration/ImportNonXmlResourceConfig-context.properties", @ImportResource(value="classpath:org/springframework/context/annotation/configuration/ImportNonXmlResourceConfig-context.properties",
reader=PropertiesBeanDefinitionReader.class) reader=PropertiesBeanDefinitionReader.class)
static class ImportNonXmlResourceConfig { static class ImportNonXmlResourceConfig {
} }
@Ignore // TODO: SPR-6327
@Test
public void testImportDifferentResourceTypes() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SubResourceConfig.class);
assertTrue(ctx.containsBean("propertiesDeclaredBean"));
assertTrue(ctx.containsBean("xmlDeclaredBean"));
}
@Configuration @Configuration
@ImportResource(value="classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml", @ImportResource(value="classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml",
reader=XmlBeanDefinitionReader.class) reader=XmlBeanDefinitionReader.class)
static class SubResourceConfig extends ImportNonXmlResourceConfig { static class SubResourceConfig extends ImportNonXmlResourceConfig {
} }
@Test
public void importWithPlaceHolder() throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
PropertySource<?> propertySource = new MapPropertySource("test",
Collections.<String, Object> singletonMap("test", "springframework"));
ctx.getEnvironment().getPropertySources().addFirst(propertySource);
ctx.register(ImportXmlConfig.class);
ctx.refresh();
assertTrue("did not contain xml-declared bean", ctx.containsBean("xmlDeclaredBean"));
}
@Configuration
@ImportResource("classpath:org/${test}/context/annotation/configuration/ImportXmlConfig-context.xml")
static class ImportWithPlaceHolder {
}
} }

View File

@ -0,0 +1,8 @@
<?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.xsd">
<bean id="otherConfigClass" class="org.springframework.context.annotation.configuration.ImportResourceTests$ImportXmlConfig"/>
</beans>