Support Class meta-annotation attributes with ASM

Prior to this commit, AnnotationAttributesReadingVisitor treated Class
annotation attributes as Strings instead of Classes. As a result,
look-ups for Class attributes in meta-annotations failed with an
IllegalArgumentException.

This commit fixes this issue by consistently treating Class attributes
as Classes in AnnotationAttributesReadingVisitor.

Issue: SPR-11557
This commit is contained in:
Sam Brannen 2014-03-18 18:20:15 +01:00
parent 42690a9a9e
commit 9ce0df89ff
5 changed files with 182 additions and 170 deletions

View File

@ -109,7 +109,7 @@ public class ComponentScanAnnotationIntegrationTests {
} }
@Test @Test
public void viaContextRegistration_WithLocallyDeclaredComposedAnnotation() { public void viaContextRegistration_WithComposedAnnotation() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ComposedAnnotationConfig.class); ctx.register(ComposedAnnotationConfig.class);
ctx.refresh(); ctx.refresh();
@ -122,19 +122,6 @@ public class ComponentScanAnnotationIntegrationTests {
ctx.containsBean("simpleComponent"), is(true)); ctx.containsBean("simpleComponent"), is(true));
} }
@Test
public void viaContextRegistration_WithExternallyDeclaredComposedAnnotation() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(org.springframework.context.annotation.componentscan.meta.ComposedAnnotationConfig.class);
ctx.refresh();
ctx.getBean(org.springframework.context.annotation.componentscan.meta.ComposedAnnotationConfig.class);
ctx.getBean(SimpleComponent.class);
assertThat("config class bean not found", ctx.containsBeanDefinition("composedAnnotationConfig"), is(true));
assertThat("@ComponentScan annotated @Configuration class registered directly against "
+ "AnnotationConfigApplicationContext did not trigger component scanning as expected",
ctx.containsBean("simpleComponent"), is(true));
}
@Test @Test
public void viaBeanRegistration() { public void viaBeanRegistration() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();

View File

@ -51,6 +51,7 @@ public class ConfigurationClassPostProcessorTests {
private DefaultListableBeanFactory beanFactory; private DefaultListableBeanFactory beanFactory;
@Before @Before
public void setUp() { public void setUp() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@ -85,8 +86,8 @@ public class ConfigurationClassPostProcessorTests {
*/ */
@Test @Test
public void alreadyLoadedConfigurationClasses() { public void alreadyLoadedConfigurationClasses() {
beanFactory.registerBeanDefinition("unloadedConfig", beanFactory.registerBeanDefinition("unloadedConfig", new RootBeanDefinition(UnloadedConfig.class.getName(),
new RootBeanDefinition(UnloadedConfig.class.getName(), null, null)); null, null));
beanFactory.registerBeanDefinition("loadedConfig", new RootBeanDefinition(LoadedConfig.class)); beanFactory.registerBeanDefinition("loadedConfig", new RootBeanDefinition(LoadedConfig.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory); pp.postProcessBeanFactory(beanFactory);
@ -111,55 +112,75 @@ public class ConfigurationClassPostProcessorTests {
} }
@Test @Test
public void postProcessorWorksWithLocallyDeclaredComposedConfiguration() { public void postProcessorWorksWithComposedConfigurationUsingReflection() {
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ComposedConfigurationClass.class)); RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); postProcessorWorksWithComposedConfiguration(beanDefinition);
pp.setEnvironment(new StandardEnvironment());
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent);
} }
@Test @Test
public void postProcessorWorksWithLocallyDeclaredComposedComposedConfiguration() { public void postProcessorWorksWithComposedConfigurationUsingAsm() {
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ComposedComposedConfigurationClass.class)); RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class.getName());
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); postProcessorWorksWithComposedConfiguration(beanDefinition);
pp.setEnvironment(new StandardEnvironment());
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent);
} }
@Test @Test
public void postProcessorWorksWithLocallyDeclaredMetaComponentScanConfiguration() { public void postProcessorWorksWithComposedConfigurationWithAttributeOverridesUsingReflection() {
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(MetaComponentScanConfigurationClass.class)); RootBeanDefinition beanDefinition = new RootBeanDefinition(
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ComposedConfigurationWithAttributeOverridesClass.class);
pp.setEnvironment(new StandardEnvironment()); postProcessorWorksWithComposedConfigurationWithAttributeOverrides(beanDefinition);
pp.postProcessBeanFactory(beanFactory); }
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent); // TODO Remove expected exception when SPR-XXXXX is resolved.
@Test(expected = ConflictingBeanDefinitionException.class)
public void postProcessorWorksWithComposedConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithComposedConfigurationWithAttributeOverrides(beanDefinition);
} }
@Test @Test
public void postProcessorWorksWithLocallyDeclaredMetaComponentScanConfigurationSubclass() { public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingReflection() {
beanFactory.registerBeanDefinition("config", new RootBeanDefinition( RootBeanDefinition beanDefinition = new RootBeanDefinition(
SubMetaComponentScanConfigurationClass.class)); ComposedComposedConfigurationWithAttributeOverridesClass.class);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); postProcessorWorksWithComposedComposedConfigurationWithAttributeOverrides(beanDefinition);
pp.setEnvironment(new StandardEnvironment()); }
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class); // TODO Remove expected exception when SPR-XXXXX is resolved.
assertNotNull(simpleComponent); @Test(expected = ConflictingBeanDefinitionException.class)
public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ComposedComposedConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithComposedComposedConfigurationWithAttributeOverrides(beanDefinition);
} }
@Test @Test
public void postProcessorWorksWithExternallyDeclaredComposedAnnotation() { public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingReflection() {
beanFactory.registerBeanDefinition("config", new RootBeanDefinition( RootBeanDefinition beanDefinition = new RootBeanDefinition(
org.springframework.context.annotation.componentscan.meta.ComposedAnnotationConfig.class)); MetaComponentScanConfigurationWithAttributeOverridesClass.class);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverrides(beanDefinition);
pp.setEnvironment(new StandardEnvironment()); }
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class); // TODO Remove expected exception when SPR-XXXXX is resolved.
assertNotNull(simpleComponent); @Test(expected = ConflictingBeanDefinitionException.class)
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
MetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverrides(beanDefinition);
}
@Test
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingReflection() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class);
postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclass(beanDefinition);
}
// TODO Remove expected exception when SPR-XXXXX is resolved.
@Test(expected = ConflictingBeanDefinitionException.class)
public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingAsm() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
SubMetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclass(beanDefinition);
} }
@Test @Test
@ -191,7 +212,8 @@ public class ConfigurationClassPostProcessorTests {
public void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() { public void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() {
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
rbd.setResource(new DescriptiveResource("XML or something")); rbd.setResource(new DescriptiveResource("XML or something"));
BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(rbd, "bar"), beanFactory, true); BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(rbd, "bar"),
beanFactory, true);
beanFactory.registerBeanDefinition("bar", proxied.getBeanDefinition()); beanFactory.registerBeanDefinition("bar", proxied.getBeanDefinition());
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
@ -278,7 +300,8 @@ public class ConfigurationClassPostProcessorTests {
RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class); RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("annotatedBean", bd); beanFactory.registerBeanDefinition("annotatedBean", bd);
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(ScopedProxyRepositoryConfiguration.class)); beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(
ScopedProxyRepositoryConfiguration.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory); pp.postProcessBeanFactory(beanFactory);
beanFactory.freezeConfiguration(); beanFactory.freezeConfiguration();
@ -313,7 +336,8 @@ public class ConfigurationClassPostProcessorTests {
RootBeanDefinition bd = new RootBeanDefinition(RepositoryFactoryBeanInjectionBean.class); RootBeanDefinition bd = new RootBeanDefinition(RepositoryFactoryBeanInjectionBean.class);
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("annotatedBean", bd); beanFactory.registerBeanDefinition("annotatedBean", bd);
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryFactoryBeanConfiguration.class)); beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(
RepositoryFactoryBeanConfiguration.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory); pp.postProcessBeanFactory(beanFactory);
beanFactory.preInstantiateSingletons(); beanFactory.preInstantiateSingletons();
@ -344,7 +368,8 @@ public class ConfigurationClassPostProcessorTests {
@Test @Test
public void genericsBasedInjectionWithWildcardWithExtendsMatch() { public void genericsBasedInjectionWithWildcardWithExtendsMatch() {
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithExtendsConfiguration.class)); beanFactory.registerBeanDefinition("configClass",
new RootBeanDefinition(WildcardWithExtendsConfiguration.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory); pp.postProcessBeanFactory(beanFactory);
@ -353,84 +378,133 @@ public class ConfigurationClassPostProcessorTests {
@Test @Test
public void genericsBasedInjectionWithWildcardWithGenericExtendsMatch() { public void genericsBasedInjectionWithWildcardWithGenericExtendsMatch() {
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithGenericExtendsConfiguration.class)); beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(
WildcardWithGenericExtendsConfiguration.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory); pp.postProcessBeanFactory(beanFactory);
assertSame(beanFactory.getBean("genericRepo"), beanFactory.getBean("repoConsumer")); 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) {
beanFactory.registerBeanDefinition("config", beanDefinition);
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.setEnvironment(new StandardEnvironment());
pp.postProcessBeanFactory(beanFactory);
SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
assertNotNull(simpleComponent);
}
// -------------------------------------------------------------------------
@Configuration @Configuration
static class SingletonBeanConfig { static class SingletonBeanConfig {
public @Bean Foo foo() { public @Bean
Foo foo() {
return new Foo(); return new Foo();
} }
public @Bean Bar bar() { public @Bean
Bar bar() {
return new Bar(foo()); return new Bar(foo());
} }
} }
static class Foo { static class Foo {
} }
static class Bar { static class Bar {
final Foo foo; final Foo foo;
public Bar(Foo foo) { public Bar(Foo foo) {
this.foo = foo; this.foo = foo;
} }
} }
@Configuration @Configuration
static class UnloadedConfig { static class UnloadedConfig {
public @Bean Foo foo() { public @Bean
Foo foo() {
return new Foo(); return new Foo();
} }
} }
@Configuration @Configuration
static class LoadedConfig { static class LoadedConfig {
public @Bean Bar bar() { public @Bean
Bar bar() {
return new Bar(new Foo()); return new Bar(new Foo());
} }
} }
public static class ScopedProxyConsumer { public static class ScopedProxyConsumer {
@Autowired @Autowired
public ITestBean testBean; public ITestBean testBean;
} }
@Configuration @Configuration
public static class ScopedProxyConfigurationClass { public static class ScopedProxyConfigurationClass {
@Bean @Lazy @Scope(proxyMode=ScopedProxyMode.INTERFACES) @Bean
@Lazy
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public ITestBean scopedClass() { public ITestBean scopedClass() {
return new TestBean(); return new TestBean();
} }
} }
public static class Repository<T> { public static class Repository<T> {
} }
public static class GenericRepository<T> extends Repository<T> { public static class GenericRepository<T> extends Repository<T> {
} }
public static class RepositoryFactoryBean<T> implements FactoryBean<T> { public static class RepositoryFactoryBean<T> implements FactoryBean<T> {
@Override @Override
@ -449,7 +523,6 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
public static class RepositoryInjectionBean { public static class RepositoryInjectionBean {
@Autowired @Autowired
@ -459,13 +532,13 @@ public class ConfigurationClassPostProcessorTests {
public Repository<Integer> integerRepository; public Repository<Integer> integerRepository;
} }
@Configuration @Configuration
public static class RepositoryConfiguration { public static class RepositoryConfiguration {
@Bean @Bean
public Repository<String> stringRepo() { public Repository<String> stringRepo() {
return new Repository<String>() { return new Repository<String>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<String>"; return "Repository<String>";
@ -476,6 +549,7 @@ public class ConfigurationClassPostProcessorTests {
@Bean @Bean
public Repository<Integer> integerRepo() { public Repository<Integer> integerRepo() {
return new Repository<Integer>() { return new Repository<Integer>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<Integer>"; return "Repository<Integer>";
@ -486,6 +560,7 @@ public class ConfigurationClassPostProcessorTests {
@Bean @Bean
public Repository<?> genericRepo() { public Repository<?> genericRepo() {
return new Repository<Object>() { return new Repository<Object>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<Object>"; return "Repository<Object>";
@ -494,13 +569,14 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Configuration @Configuration
public static class ScopedRepositoryConfiguration { public static class ScopedRepositoryConfiguration {
@Bean @Scope("prototype") @Bean
@Scope("prototype")
public Repository<String> stringRepo() { public Repository<String> stringRepo() {
return new Repository<String>() { return new Repository<String>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<String>"; return "Repository<String>";
@ -508,9 +584,11 @@ public class ConfigurationClassPostProcessorTests {
}; };
} }
@Bean @Scope("prototype") @Bean
@Scope("prototype")
public Repository<Integer> integerRepo() { public Repository<Integer> integerRepo() {
return new Repository<Integer>() { return new Repository<Integer>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<Integer>"; return "Repository<Integer>";
@ -518,10 +596,12 @@ public class ConfigurationClassPostProcessorTests {
}; };
} }
@Bean @Scope("prototype") @Bean
@Scope("prototype")
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public Repository genericRepo() { public Repository genericRepo() {
return new Repository<Object>() { return new Repository<Object>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<Object>"; return "Repository<Object>";
@ -530,13 +610,14 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Configuration @Configuration
public static class ScopedProxyRepositoryConfiguration { public static class ScopedProxyRepositoryConfiguration {
@Bean @Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS) @Bean
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Repository<String> stringRepo() { public Repository<String> stringRepo() {
return new Repository<String>() { return new Repository<String>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<String>"; return "Repository<String>";
@ -544,9 +625,11 @@ public class ConfigurationClassPostProcessorTests {
}; };
} }
@Bean @Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS) @Bean
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Repository<Integer> integerRepo() { public Repository<Integer> integerRepo() {
return new Repository<Integer>() { return new Repository<Integer>() {
@Override @Override
public String toString() { public String toString() {
return "Repository<Integer>"; return "Repository<Integer>";
@ -555,14 +638,12 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
public static class SpecificRepositoryInjectionBean { public static class SpecificRepositoryInjectionBean {
@Autowired @Autowired
public GenericRepository<?> genericRepository; public GenericRepository<?> genericRepository;
} }
@Configuration @Configuration
public static class SpecificRepositoryConfiguration { public static class SpecificRepositoryConfiguration {
@ -572,7 +653,6 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
public static class RepositoryFactoryBeanInjectionBean { public static class RepositoryFactoryBeanInjectionBean {
@Autowired @Autowired
@ -587,7 +667,6 @@ public class ConfigurationClassPostProcessorTests {
public RepositoryFactoryBean<?> prefixQualifiedRepositoryFactoryBean; public RepositoryFactoryBean<?> prefixQualifiedRepositoryFactoryBean;
} }
@Configuration @Configuration
public static class RepositoryFactoryBeanConfiguration { public static class RepositoryFactoryBeanConfiguration {
@ -597,7 +676,6 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Configuration @Configuration
public static class RawMatchingConfiguration { public static class RawMatchingConfiguration {
@ -613,7 +691,6 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Configuration @Configuration
public static class WildcardMatchingConfiguration { public static class WildcardMatchingConfiguration {
@ -629,7 +706,6 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Configuration @Configuration
public static class WildcardWithExtendsConfiguration { public static class WildcardWithExtendsConfiguration {
@ -649,7 +725,6 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Configuration @Configuration
public static class WildcardWithGenericExtendsConfiguration { public static class WildcardWithGenericExtendsConfiguration {
@ -670,26 +745,39 @@ public class ConfigurationClassPostProcessorTests {
} }
@Configuration @Configuration
@ComponentScan @ComponentScan(basePackages = "org.springframework.context.annotation.componentscan.simple")
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public static @interface ComposedConfiguration { public static @interface ComposedConfiguration {
String[] basePackages() default {};
}
@ComposedConfiguration(basePackages = "org.springframework.context.annotation.componentscan.simple")
public static class ComposedConfigurationClass {
} }
@ComposedConfiguration @ComposedConfiguration
public static class ComposedConfigurationClass {
}
@Configuration
@ComponentScan
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public static @interface ComposedComposedConfiguration { public static @interface ComposedConfigurationWithAttributeOverrides {
String[] basePackages() default {}; String[] basePackages() default {};
} }
@ComposedComposedConfiguration(basePackages = "org.springframework.context.annotation.componentscan.simple") @ComposedConfigurationWithAttributeOverrides(basePackages = "org.springframework.context.annotation.componentscan.simple")
public static class ComposedComposedConfigurationClass { public static class ComposedConfigurationWithAttributeOverridesClass {
}
@ComposedConfigurationWithAttributeOverrides
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public static @interface ComposedComposedConfigurationWithAttributeOverrides {
String[] basePackages() default {};
}
@ComposedComposedConfigurationWithAttributeOverrides(basePackages = "org.springframework.context.annotation.componentscan.simple")
public static class ComposedComposedConfigurationWithAttributeOverridesClass {
} }
@ComponentScan @ComponentScan
@ -702,16 +790,18 @@ public class ConfigurationClassPostProcessorTests {
@Configuration @Configuration
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public static @interface MetaComponentScanConfiguration { public static @interface MetaComponentScanConfigurationWithAttributeOverrides {
String[] basePackages() default {}; String[] basePackages() default {};
} }
@MetaComponentScanConfiguration(basePackages = "org.springframework.context.annotation.componentscan.simple") @MetaComponentScanConfigurationWithAttributeOverrides(basePackages = "org.springframework.context.annotation.componentscan.simple")
public static class MetaComponentScanConfigurationClass { public static class MetaComponentScanConfigurationWithAttributeOverridesClass {
} }
@Configuration @Configuration
public static class SubMetaComponentScanConfigurationClass extends MetaComponentScanConfigurationClass { public static class SubMetaComponentScanConfigurationWithAttributeOverridesClass extends
MetaComponentScanConfigurationWithAttributeOverridesClass {
} }
} }

View File

@ -1,26 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation.componentscan.meta;
/**
* @author Sam Brannen
* @since 4.0.3
*/
@ComposedConfiguration(basePackages = "org.springframework.context.annotation.componentscan.simple")
public class ComposedAnnotationConfig {
}

View File

@ -1,40 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation.componentscan.meta;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Composed annotation, combining {@link Configuration @Configuration} and
* {@link ComponentScan @ComponentScan}.
*
* @author Sam Brannen
* @since 4.0.3
*/
@Configuration
@ComponentScan
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComposedConfiguration {
String[] basePackages() default {};
}

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.
@ -43,6 +43,7 @@ import org.springframework.util.ReflectionUtils;
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Phillip Webb * @author Phillip Webb
* @author Sam Brannen
* @since 3.1.1 * @since 3.1.1
*/ */
abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor { abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor {
@ -279,7 +280,7 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib
// otherwise, and don't want to mess with accessibility in a SecurityManager environment. // otherwise, and don't want to mess with accessibility in a SecurityManager environment.
if (Modifier.isPublic(annotation.annotationType().getModifiers())) { if (Modifier.isPublic(annotation.annotationType().getModifiers())) {
this.attributesMap.add(annotation.annotationType().getName(), this.attributesMap.add(annotation.annotationType().getName(),
AnnotationUtils.getAnnotationAttributes(annotation, true, true)); AnnotationUtils.getAnnotationAttributes(annotation, false, true));
for (Annotation metaMetaAnnotation : annotation.annotationType().getAnnotations()) { for (Annotation metaMetaAnnotation : annotation.annotationType().getAnnotations()) {
recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation); recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation);
} }