Support meta-annotation overrides in ASM processing

Prior to this commit, Spring supported meta-annotation attribute
overrides in custom composed annotations with reflection-based
annotation processing but not with ASM-based annotation processing.

This commit ensures that meta-annotation attribute overrides are
supported in AnnotationMetadataReadingVisitor.getAnnotationAttributes().

Issue: SPR-11574
This commit is contained in:
Sam Brannen
2014-03-19 23:44:13 +01:00
parent 1bab8a3916
commit 99cd2f6098
9 changed files with 242 additions and 146 deletions

View File

@@ -23,6 +23,19 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashSet;
import org.junit.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.CustomAutowireConfigurer;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.ComponentScanParserTests.KustomAnnotationAutowiredBean;
import org.springframework.context.annotation.componentscan.simple.SimpleComponent;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.tests.context.SimpleMapScope;
import org.springframework.util.SerializationTestUtils;
import example.scannable.CustomComponent;
import example.scannable.CustomStereotype;
import example.scannable.DefaultNamedComponent;
@@ -33,19 +46,6 @@ import example.scannable_implicitbasepackage.ComponentScanAnnotatedConfigWithImp
import example.scannable_scoped.CustomScopeAnnotationBean;
import example.scannable_scoped.MyScope;
import org.junit.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.CustomAutowireConfigurer;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.ComponentScanParserTests.CustomAnnotationAutowiredBean;
import org.springframework.context.annotation.componentscan.simple.SimpleComponent;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.tests.context.SimpleMapScope;
import org.springframework.util.SerializationTestUtils;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
@@ -159,7 +159,7 @@ public class ComponentScanAnnotationIntegrationTests {
@Test
public void withCustomTypeFilter() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ComponentScanWithCustomTypeFilter.class);
CustomAnnotationAutowiredBean testBean = ctx.getBean(CustomAnnotationAutowiredBean.class);
KustomAnnotationAutowiredBean testBean = ctx.getBean(KustomAnnotationAutowiredBean.class);
assertThat(testBean.getDependency(), notNullValue());
}
@@ -304,8 +304,8 @@ class ComponentScanWithCustomTypeFilter {
return cac;
}
public ComponentScanParserTests.CustomAnnotationAutowiredBean testBean() {
return new ComponentScanParserTests.CustomAnnotationAutowiredBean();
public ComponentScanParserTests.KustomAnnotationAutowiredBean testBean() {
return new ComponentScanParserTests.KustomAnnotationAutowiredBean();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@@ -45,6 +45,7 @@ import example.scannable.AutowiredQualifierFooService;
* @author Mark Fisher
* @author Juergen Hoeller
* @author Chris Beams
* @author Sam Brannen
*/
public class ComponentScanParserTests {
@@ -84,7 +85,7 @@ public class ComponentScanParserTests {
public void testCustomAnnotationUsedForBothComponentScanAndQualifier() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/context/annotation/customAnnotationUsedForBothComponentScanAndQualifierTests.xml");
CustomAnnotationAutowiredBean testBean = (CustomAnnotationAutowiredBean) context.getBean("testBean");
KustomAnnotationAutowiredBean testBean = (KustomAnnotationAutowiredBean) context.getBean("testBean");
assertNotNull(testBean.getDependency());
}
@@ -92,7 +93,7 @@ public class ComponentScanParserTests {
public void testCustomTypeFilter() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/context/annotation/customTypeFilterTests.xml");
CustomAnnotationAutowiredBean testBean = (CustomAnnotationAutowiredBean) context.getBean("testBean");
KustomAnnotationAutowiredBean testBean = (KustomAnnotationAutowiredBean) context.getBean("testBean");
assertNotNull(testBean.getDependency());
}
@@ -128,28 +129,36 @@ public class ComponentScanParserTests {
}
public static class CustomAnnotationAutowiredBean {
/**
* Intentionally spelling "custom" with a "k" since there are numerous
* classes in this package named *Custom*.
*/
public static class KustomAnnotationAutowiredBean {
@Autowired
@CustomAnnotation
private CustomAnnotationDependencyBean dependency;
private KustomAnnotationDependencyBean dependency;
public CustomAnnotationDependencyBean getDependency() {
public KustomAnnotationDependencyBean getDependency() {
return this.dependency;
}
}
@CustomAnnotation
public static class CustomAnnotationDependencyBean {
public static class KustomAnnotationDependencyBean {
}
public static class CustomTypeFilter implements TypeFilter {
/**
* Intentionally spelling "custom" with a "k" since there are numerous
* classes in this package named *Custom*.
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
return metadataReader.getClassMetadata().getClassName().contains("Custom");
return metadataReader.getClassMetadata().getClassName().contains("Kustom");
}
}

View File

@@ -114,73 +114,69 @@ public class ConfigurationClassPostProcessorTests {
@Test
public void postProcessorWorksWithComposedConfigurationUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class);
postProcessorWorksWithComposedConfiguration(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithComposedConfigurationUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class.getName());
postProcessorWorksWithComposedConfiguration(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithComposedConfigurationWithAttributeOverridesUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedConfigurationWithAttributeOverridesClass.class);
postProcessorWorksWithComposedConfigurationWithAttributeOverrides(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
// TODO Remove expected exception when SPR-11574 is resolved.
@Test(expected = ConflictingBeanDefinitionException.class)
@Test
public void postProcessorWorksWithComposedConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithComposedConfigurationWithAttributeOverrides(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedComposedConfigurationWithAttributeOverridesClass.class);
postProcessorWorksWithComposedComposedConfigurationWithAttributeOverrides(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
// TODO Remove expected exception when SPR-11574 is resolved.
@Test(expected = ConflictingBeanDefinitionException.class)
@Test
public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedComposedConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithComposedComposedConfigurationWithAttributeOverrides(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
MetaComponentScanConfigurationWithAttributeOverridesClass.class);
postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverrides(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
// TODO Remove expected exception when SPR-11574 is resolved.
@Test(expected = ConflictingBeanDefinitionException.class)
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
MetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverrides(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class);
postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclass(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
// TODO Remove expected exception when SPR-11574 is resolved.
@Test(expected = ConflictingBeanDefinitionException.class)
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclass(beanDefinition);
assertSupportForComposedAnnotation(beanDefinition);
}
@Test
@@ -386,46 +382,7 @@ public class ConfigurationClassPostProcessorTests {
assertSame(beanFactory.getBean("genericRepo"), beanFactory.getBean("repoConsumer"));
}
private void postProcessorWorksWithComposedConfiguration(RootBeanDefinition beanDefinition) {
beanFactory.registerBeanDefinition("config", beanDefinition);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.setEnvironment(new StandardEnvironment());
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent);
}
private void postProcessorWorksWithComposedConfigurationWithAttributeOverrides(RootBeanDefinition beanDefinition) {
beanFactory.registerBeanDefinition("config", beanDefinition);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.setEnvironment(new StandardEnvironment());
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent);
}
private void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverrides(
RootBeanDefinition beanDefinition) {
beanFactory.registerBeanDefinition("config", beanDefinition);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.setEnvironment(new StandardEnvironment());
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent);
}
private void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverrides(
RootBeanDefinition beanDefinition) {
beanFactory.registerBeanDefinition("config", beanDefinition);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.setEnvironment(new StandardEnvironment());
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent);
}
private void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclass(
RootBeanDefinition beanDefinition) {
private void assertSupportForComposedAnnotation(RootBeanDefinition beanDefinition) {
beanFactory.registerBeanDefinition("config", beanDefinition);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.setEnvironment(new StandardEnvironment());

View File

@@ -17,6 +17,6 @@
</property>
</bean>
<bean id="testBean" class="org.springframework.context.annotation.ComponentScanParserTests$CustomAnnotationAutowiredBean"/>
<bean id="testBean" class="org.springframework.context.annotation.ComponentScanParserTests$KustomAnnotationAutowiredBean"/>
</beans>

View File

@@ -17,6 +17,6 @@
</property>
</bean>
<bean id="testBean" class="org.springframework.context.annotation.ComponentScanParserTests$CustomAnnotationAutowiredBean"/>
<bean id="testBean" class="org.springframework.context.annotation.ComponentScanParserTests$KustomAnnotationAutowiredBean"/>
</beans>