Find all @ComponentScan and @PropertySource annotations
Prior to this commit, Spring failed to find multiple composed @ComponentScan and @PropertySource annotations or multiple @ComponentScans and @PropertySources container annotations. The reason was due to lacking support in the AnnotatedTypeMetadata API. This commit introduces support for finding all @ComponentScan and @PropertySource annotations by making use of the new getMergedRepeatableAnnotationAttributes() method in AnnotatedTypeMetadata. Closes gh-30941 See gh-31041
This commit is contained in:
@@ -44,6 +44,7 @@ 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.ApplicationContext;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
@@ -143,6 +144,15 @@ public class ComponentScanAnnotationIntegrationTests {
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleComposedComponentScanAnnotations() { // gh-30941
|
||||
ApplicationContext ctx = new AnnotationConfigApplicationContext(MultipleComposedAnnotationsConfig.class);
|
||||
ctx.getBean(MultipleComposedAnnotationsConfig.class);
|
||||
assertContextContainsBean(ctx, "componentScanAnnotationIntegrationTests.MultipleComposedAnnotationsConfig");
|
||||
assertContextContainsBean(ctx, "simpleComponent");
|
||||
assertContextContainsBean(ctx, "barComponent");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viaBeanRegistration() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
@@ -267,6 +277,10 @@ public class ComponentScanAnnotationIntegrationTests {
|
||||
assertThat(ctx.containsBean("fooServiceImpl")).isTrue();
|
||||
}
|
||||
|
||||
private static void assertContextContainsBean(ApplicationContext ctx, String beanName) {
|
||||
assertThat(ctx.containsBean(beanName)).as("context contains bean " + beanName).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@@ -278,10 +292,25 @@ public class ComponentScanAnnotationIntegrationTests {
|
||||
String[] basePackages() default {};
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ComposedConfiguration2 {
|
||||
|
||||
@AliasFor(annotation = ComponentScan.class)
|
||||
String[] basePackages() default {};
|
||||
}
|
||||
|
||||
@ComposedConfiguration(basePackages = "org.springframework.context.annotation.componentscan.simple")
|
||||
public static class ComposedAnnotationConfig {
|
||||
}
|
||||
|
||||
@ComposedConfiguration(basePackages = "org.springframework.context.annotation.componentscan.simple")
|
||||
@ComposedConfiguration2(basePackages = "example.scannable.sub")
|
||||
static class MultipleComposedAnnotationsConfig {
|
||||
}
|
||||
|
||||
public static class AwareTypeFilter implements TypeFilter, EnvironmentAware,
|
||||
ResourceLoaderAware, BeanClassLoaderAware, BeanFactoryAware {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -32,6 +32,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -239,6 +240,14 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleComposedPropertySourceAnnotations() { // gh-30941
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(MultipleComposedAnnotationsConfig.class);
|
||||
ctx.getBean(MultipleComposedAnnotationsConfig.class);
|
||||
assertEnvironmentContainsProperties(ctx, "from.p1", "from.p2", "from.p3", "from.p4", "from.p5");
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void withNamedPropertySources() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithNamedPropertySources.class);
|
||||
@@ -305,6 +314,17 @@ class PropertySourceAnnotationTests {
|
||||
}
|
||||
|
||||
|
||||
private static void assertEnvironmentContainsProperties(ApplicationContext ctx, String... names) {
|
||||
for (String name : names) {
|
||||
assertThat(ctx.getEnvironment().containsProperty(name)).as("environment contains property " + name).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertEnvironmentContainsProperty(ApplicationContext ctx, String name) {
|
||||
assertThat(ctx.getEnvironment().containsProperty(name)).as("environment contains property " + name).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:${unresolvable}/p1.properties")
|
||||
static class ConfigWithUnresolvablePlaceholder {
|
||||
@@ -496,6 +516,28 @@ class PropertySourceAnnotationTests {
|
||||
static class ConfigWithRepeatedPropertySourceAnnotationsOnComposedAnnotation {
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p1.properties")
|
||||
@interface PropertySource1 {
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p2.properties")
|
||||
@PropertySources({
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p3.properties"),
|
||||
})
|
||||
@interface PropertySource23 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@PropertySource1
|
||||
@PropertySource23
|
||||
@PropertySources({
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p4.properties")
|
||||
})
|
||||
@PropertySource("classpath:org/springframework/context/annotation/p5.properties")
|
||||
static class MultipleComposedAnnotationsConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@PropertySources({
|
||||
|
||||
Reference in New Issue
Block a user