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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user