SPR-6328: Rename @ImportXml -> @ImportResource and allow for usage of non-XML BeanDefinitionReader types

This commit is contained in:
Chris Beams 2009-11-11 00:48:30 +00:00
parent 81efd48352
commit ee553f7804
7 changed files with 83 additions and 26 deletions

View File

@ -24,6 +24,7 @@ import java.util.Set;
import org.springframework.beans.factory.parsing.Location; import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.core.io.DescriptiveResource; import org.springframework.core.io.DescriptiveResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
@ -50,7 +51,7 @@ final class ConfigurationClass {
private String beanName; private String beanName;
private final Set<String> xmlFilesToImport = new LinkedHashSet<String>(); private final Map<String, String> importedResources = new LinkedHashMap<String, String>();
private final Set<ConfigurationClassMethod> methods = new LinkedHashSet<ConfigurationClassMethod>(); private final Set<ConfigurationClassMethod> methods = new LinkedHashSet<ConfigurationClassMethod>();
@ -107,12 +108,12 @@ final class ConfigurationClass {
return this.methods; return this.methods;
} }
public void addXmlImport(String xmlImport) { public void addImportedResource(String importedResource, String readerClassName) {
this.xmlFilesToImport.add(xmlImport); this.importedResources.put(importedResource, readerClassName);
} }
public Set<String> getXmlImports() { public Map<String, String> getImportedResources() {
return this.xmlFilesToImport; return this.importedResources;
} }

View File

@ -19,6 +19,7 @@ package org.springframework.context.annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -36,11 +37,12 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
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;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.MethodMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -95,7 +97,7 @@ class ConfigurationClassBeanDefinitionReader {
loadBeanDefinitionsForModelMethod(method); loadBeanDefinitionsForModelMethod(method);
} }
loadBeanDefinitionsFromXml(configClass.getXmlImports()); loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
} }
/** /**
@ -212,10 +214,29 @@ class ConfigurationClassBeanDefinitionReader {
registry.registerBeanDefinition(beanName, beanDefToRegister); registry.registerBeanDefinition(beanName, beanDefToRegister);
} }
private void loadBeanDefinitionsFromXml(Set<String> xmlImports) { private void loadBeanDefinitionsFromImportedResources(Map<String, String> importedResources) {
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.registry);
// TODO SPR-6310: qualify relatively pathed locations as done in AbstractContextLoader.modifyLocations HashMap<String, BeanDefinitionReader> readerInstanceCache = new HashMap<String, BeanDefinitionReader>();
reader.loadBeanDefinitions(xmlImports.toArray(new String[]{}));
for (String resource : importedResources.keySet()) {
String readerClassName = importedResources.get(resource);
if (!readerInstanceCache.containsKey(readerClassName)) {
try {
@SuppressWarnings("unchecked")
Class<? extends BeanDefinitionReader> readerClass =
(Class<? extends BeanDefinitionReader>) ClassUtils.forName(readerClassName, ClassUtils.getDefaultClassLoader());
BeanDefinitionReader readerInstance = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
readerInstanceCache.put(readerClassName, readerInstance);
} catch (Exception ex) {
ReflectionUtils.handleReflectionException(ex);
}
}
BeanDefinitionReader reader = readerInstanceCache.get(readerClassName);
// TODO SPR-6310: qualify relatively pathed locations as done in AbstractContextLoader.modifyLocations
reader.loadBeanDefinitions(importedResources.keySet().toArray(new String[]{}));
}
} }
/** /**

View File

@ -28,12 +28,14 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.Location; import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
/** /**
* Parses a {@link Configuration} class definition, populating a model (collection) of * Parses a {@link Configuration} class definition, populating a model (collection) of
@ -128,9 +130,10 @@ class ConfigurationClassParser {
if (metadata.isAnnotated(Import.class.getName())) { if (metadata.isAnnotated(Import.class.getName())) {
processImport(configClass, (String[]) metadata.getAnnotationAttributes(Import.class.getName()).get("value")); processImport(configClass, (String[]) metadata.getAnnotationAttributes(Import.class.getName()).get("value"));
} }
if (metadata.isAnnotated(ImportXml.class.getName())) { if (metadata.isAnnotated(ImportResource.class.getName())) {
for (String xmlImport : (String[]) metadata.getAnnotationAttributes(ImportXml.class.getName()).get("value")) { String readerClassName = (String) metadata.getAnnotationAttributes(ImportResource.class.getName()).get("reader");
configClass.addXmlImport(xmlImport); for (String importedResource : (String[]) metadata.getAnnotationAttributes(ImportResource.class.getName()).get("value")) {
configClass.addImportedResource(importedResource, readerClassName);
} }
} }
Set<MethodMetadata> methods = metadata.getAnnotatedMethods(Bean.class.getName()); Set<MethodMetadata> methods = metadata.getAnnotatedMethods(Bean.class.getName());

View File

@ -23,12 +23,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Documented @Documented
@Inherited public @interface ImportResource {
public @interface ImportXml {
String[] value(); String[] value();
Class<? extends BeanDefinitionReader> reader() default XmlBeanDefinitionReader.class;
} }

View File

@ -26,20 +26,22 @@ import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
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.support.PropertiesBeanDefinitionReader;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportXml; import org.springframework.context.annotation.ImportResource;
import test.beans.TestBean; import test.beans.TestBean;
/** /**
* Integration tests for {@link ImportXml} support. * Integration tests for {@link ImportResource} support.
* *
* @author Chris Beams * @author Chris Beams
*/ */
public class ImportXmlTests { public class ImportResourceTests {
@Test @Test
public void testImportXml() { public void testImportXml() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlConfig.class); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportXmlConfig.class);
@ -48,7 +50,7 @@ public class ImportXmlTests {
} }
@Configuration @Configuration
@ImportXml("classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml") @ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml")
static class ImportXmlConfig { static class ImportXmlConfig {
public @Bean TestBean javaDeclaredBean() { public @Bean TestBean javaDeclaredBean() {
return new TestBean("java.declared"); return new TestBean("java.declared");
@ -64,7 +66,7 @@ public class ImportXmlTests {
} }
@Configuration @Configuration
@ImportXml("ImportXmlConfig-context.xml") @ImportResource("ImportXmlConfig-context.xml")
static class ImportXmlWithRelativePathConfig { static class ImportXmlWithRelativePathConfig {
public @Bean TestBean javaDeclaredBean() { public @Bean TestBean javaDeclaredBean() {
return new TestBean("java.declared"); return new TestBean("java.declared");
@ -97,7 +99,7 @@ public class ImportXmlTests {
} }
@Configuration @Configuration
@ImportXml("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 {
} }
@ -106,7 +108,7 @@ public class ImportXmlTests {
} }
@Configuration @Configuration
@ImportXml("classpath:org/springframework/context/annotation/configuration/SecondLevelSubConfig-context.xml") @ImportResource("classpath:org/springframework/context/annotation/configuration/SecondLevelSubConfig-context.xml")
static class SecondLevelSubConfig extends BaseConfig { static class SecondLevelSubConfig extends BaseConfig {
} }
@ -118,7 +120,7 @@ public class ImportXmlTests {
} }
@Configuration @Configuration
@ImportXml("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 {
} }
@ -136,7 +138,7 @@ public class ImportXmlTests {
} }
@Configuration @Configuration
@ImportXml(value="classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml") @ImportResource(value="classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml")
static class ImportXmlAutowiredConfig { static class ImportXmlAutowiredConfig {
@Autowired TestBean xmlDeclaredBean; @Autowired TestBean xmlDeclaredBean;
@ -144,5 +146,30 @@ public class ImportXmlTests {
return xmlDeclaredBean.getName(); return xmlDeclaredBean.getName();
} }
} }
@Test
public void testImportNonXmlResource() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportNonXmlResourceConfig.class);
assertTrue(ctx.containsBean("propertiesDeclaredBean"));
}
@Configuration
@ImportResource(value="classpath:org/springframework/context/annotation/configuration/ImportNonXmlResourceConfig-context.properties",
reader=PropertiesBeanDefinitionReader.class)
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
@ImportResource(value="classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml",
reader=XmlBeanDefinitionReader.class)
static class SubResourceConfig extends ImportNonXmlResourceConfig {
}
} }

View File

@ -7,7 +7,7 @@
<bean id="proxiedXmlBean" class="test.beans.TestBean"/> <bean id="proxiedXmlBean" class="test.beans.TestBean"/>
<bean id="anAspect" class="org.springframework.context.annotation.configuration.ImportXmlTests$AnAspect"/> <bean id="anAspect" class="org.springframework.context.annotation.configuration.ImportResourceTests$AnAspect"/>
<aop:aspectj-autoproxy> <aop:aspectj-autoproxy>
<aop:include name="anAspect"/> <aop:include name="anAspect"/>