Allow multiple @Filter 'value' args for concision
Prior to this change, to specify two or more annotation include/exclude
filters, one would declare @ComponentScan as follows:
@ComponentScan(basePackages="example.scannable",
useDefaultFilters=false,
includeFilters={
@Filter(MyStereotype.class),
@Filter(MyComponent.class)
})
This was because @Filter's 'value' attribute accepted exactly one
argument.
Now, any given @Filter may accept one or more value arguments, allowing
for more concise @ComponentScan declarations:
@ComponentScan(basePackages="example.scannable",
useDefaultFilters=false,
includeFilters=@Filter({MyStereotype.class, MyComponent.class}))
Supplying multiple arguments in this way assumes that they are the same
type of filter, e.g. ANNOTATION, ASSIGNABLE_TYPE, or CUSTOM. To declare
multiple *different* types of filters, multiple @Filter annotations are
still required, e.g.:
@ComponentScan(
includeFilters={
@Filter(type=ANNOTATION, value=MyStereotype.class),
@Filter(type=ASSIGNABLE_TYPE, value={Foo.class, Bar.class})
})
Note that specifying zero arguments, e.g. @Filter({}) is nonsensical; it
will have no effect on component scanning, but does not raise an error.
Issue: SPR-8881
This commit is contained in:
@@ -41,7 +41,11 @@ import org.springframework.context.annotation.ComponentScanParserTests.CustomAnn
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import example.scannable.CustomComponent;
|
||||
import example.scannable.CustomStereotype;
|
||||
import example.scannable.DefaultNamedComponent;
|
||||
import example.scannable.FooService;
|
||||
import example.scannable.MessageBean;
|
||||
import example.scannable.ScopedProxyTestBean;
|
||||
import example.scannable_scoped.CustomScopeAnnotationBean;
|
||||
import example.scannable_scoped.MyScope;
|
||||
@@ -159,6 +163,24 @@ public class ComponentScanAnnotationIntegrationTests {
|
||||
assertThat(deserialized.foo(1), equalTo("bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withMultipleAnnotationIncludeFilters1() throws IOException, ClassNotFoundException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ComponentScanWithMultipleAnnotationIncludeFilters1.class);
|
||||
ctx.refresh();
|
||||
ctx.getBean(DefaultNamedComponent.class); // @CustomStereotype-annotated
|
||||
ctx.getBean(MessageBean.class); // @CustomComponent-annotated
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withMultipleAnnotationIncludeFilters2() throws IOException, ClassNotFoundException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ComponentScanWithMultipleAnnotationIncludeFilters2.class);
|
||||
ctx.refresh();
|
||||
ctx.getBean(DefaultNamedComponent.class); // @CustomStereotype-annotated
|
||||
ctx.getBean(MessageBean.class); // @CustomComponent-annotated
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withBasePackagesAndValueAlias() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -222,7 +244,7 @@ class MyScopeMetadataResolver extends AnnotationScopeMetadataResolver {
|
||||
class ComponentScanWithCustomTypeFilter {
|
||||
@Bean
|
||||
@SuppressWarnings({ "rawtypes", "serial", "unchecked" })
|
||||
public CustomAutowireConfigurer customAutowireConfigurer() {
|
||||
public static CustomAutowireConfigurer customAutowireConfigurer() {
|
||||
CustomAutowireConfigurer cac = new CustomAutowireConfigurer();
|
||||
cac.setCustomQualifierTypes(new HashSet() {{ add(ComponentScanParserTests.CustomAnnotation.class); }});
|
||||
return cac;
|
||||
@@ -240,6 +262,23 @@ class ComponentScanWithCustomTypeFilter {
|
||||
includeFilters=@Filter(type=FilterType.ASSIGNABLE_TYPE, value=ScopedProxyTestBean.class))
|
||||
class ComponentScanWithScopedProxy { }
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages="example.scannable",
|
||||
useDefaultFilters=false,
|
||||
includeFilters={
|
||||
@Filter(CustomStereotype.class),
|
||||
@Filter(CustomComponent.class)
|
||||
}
|
||||
)
|
||||
class ComponentScanWithMultipleAnnotationIncludeFilters1 { }
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages="example.scannable",
|
||||
useDefaultFilters=false,
|
||||
includeFilters=@Filter({CustomStereotype.class, CustomComponent.class})
|
||||
)
|
||||
class ComponentScanWithMultipleAnnotationIncludeFilters2 { }
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(
|
||||
value="example.scannable",
|
||||
|
||||
Reference in New Issue
Block a user