@Enable registrars called with correct metadata when placed on superclass

Issue: SPR-11251
This commit is contained in:
Juergen Hoeller 2013-12-23 23:07:59 +01:00
parent e08f743301
commit ecee20f1fe
2 changed files with 28 additions and 14 deletions

View File

@ -59,8 +59,6 @@ import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import static org.springframework.context.annotation.MetadataUtils.*;
/**
* Parses a {@link Configuration} class definition, populating a collection of
* {@link ConfigurationClass} objects (parsing a single Configuration class may result in
@ -172,20 +170,19 @@ class ConfigurationClassParser {
/**
* @return annotation metadata of superclass, {@code null} if none found or previously processed
*/
protected AnnotationMetadata doProcessConfigurationClass(
ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {
protected AnnotationMetadata doProcessConfigurationClass(ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {
// recursively process any member (nested) classes first
processMemberClasses(metadata);
// process any @PropertySource annotations
AnnotationAttributes propertySource = attributesFor(metadata, org.springframework.context.annotation.PropertySource.class);
AnnotationAttributes propertySource = MetadataUtils.attributesFor(metadata,
org.springframework.context.annotation.PropertySource.class);
if (propertySource != null) {
processPropertySource(propertySource);
}
// process any @ComponentScan annotations
AnnotationAttributes componentScan = attributesFor(metadata, ComponentScan.class);
AnnotationAttributes componentScan = MetadataUtils.attributesFor(metadata, ComponentScan.class);
if (componentScan != null) {
// the config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
@ -204,12 +201,12 @@ class ConfigurationClassParser {
Set<Object> visited = new LinkedHashSet<Object>();
collectImports(metadata, imports, visited);
if (!imports.isEmpty()) {
processImport(configClass, imports, true);
processImport(configClass, metadata, imports, true);
}
// process any @ImportResource annotations
if (metadata.isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource = attributesFor(metadata, ImportResource.class);
AnnotationAttributes importResource = MetadataUtils.attributesFor(metadata, ImportResource.class);
String[] resources = importResource.getStringArray("value");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
@ -369,13 +366,14 @@ class ConfigurationClassParser {
}
}
private void processImport(ConfigurationClass configClass, Collection<?> classesToImport, boolean checkForCircularImports) throws IOException {
private void processImport(ConfigurationClass configClass, AnnotationMetadata metadata,
Collection<?> classesToImport, boolean checkForCircularImports) throws IOException {
if (checkForCircularImports && this.importStack.contains(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
}
else {
this.importStack.push(configClass);
AnnotationMetadata importingClassMetadata = configClass.getMetadata();
try {
for (Object candidate : classesToImport) {
Object candidateToCheck = (candidate instanceof Class ? (Class) candidate :
@ -385,7 +383,7 @@ class ConfigurationClassParser {
Class<?> candidateClass = (candidate instanceof Class ? (Class) candidate :
this.resourceLoader.getClassLoader().loadClass((String) candidate));
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
processImport(configClass, Arrays.asList(selector.selectImports(importingClassMetadata)), false);
processImport(configClass, metadata, Arrays.asList(selector.selectImports(metadata)), false);
}
else if (checkAssignability(ImportBeanDefinitionRegistrar.class, candidateToCheck)) {
// the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
@ -393,11 +391,11 @@ class ConfigurationClassParser {
this.resourceLoader.getClassLoader().loadClass((String) candidate));
ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
invokeAwareMethods(registrar);
registrar.registerBeanDefinitions(importingClassMetadata, this.registry);
registrar.registerBeanDefinitions(metadata, this.registry);
}
else {
// candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class
this.importStack.registerImport(importingClassMetadata,
this.importStack.registerImport(metadata,
(candidate instanceof Class ? ((Class) candidate).getName() : (String) candidate));
processConfigurationClass(candidateToCheck instanceof Class ? new ConfigurationClass((Class) candidateToCheck, true) :
new ConfigurationClass((MetadataReader) candidateToCheck, true));

View File

@ -52,6 +52,17 @@ public class EnableTransactionManagementTests {
assertThat("Stereotype annotation not visible", services.containsKey("testBean"), is(true));
}
@Test
public void transactionProxyIsCreatedWithEnableOnSuperclass() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(InheritedEnableTxConfig.class, TxManagerConfig.class);
ctx.refresh();
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
assertThat("testBean is not a proxy", AopUtils.isAopProxy(bean), is(true));
Map<?,?> services = ctx.getBeansWithAnnotation(Service.class);
assertThat("Stereotype annotation not visible", services.containsKey("testBean"), is(true));
}
@Test
public void txManagerIsResolvedOnInvocationOfTransactionalMethod() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
@ -97,6 +108,11 @@ public class EnableTransactionManagementTests {
}
@Configuration
static class InheritedEnableTxConfig extends EnableTxConfig {
}
@Configuration
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
static class EnableAspectJTxConfig {