Support inferred base package for @ComponentScan

Prior to this change, @ComponentScan required the declaration of
exactly one of the #value, #basePackage or #basePackageClasses
attributes in order to determine which package(s) to scan.

This commit introduces support for base package inference, relaxing the
above requirement and falling back to scanning the package in which the
@ComponentScan-annotated class is declared.

Issue: SPR-9586
This commit is contained in:
Phillip Webb
2012-09-06 19:56:38 -07:00
committed by Chris Beams
parent 512ffbb273
commit 73832f8c6e
7 changed files with 91 additions and 25 deletions

View File

@@ -30,7 +30,9 @@ import org.springframework.core.type.filter.TypeFilter;
* Provides support parallel with Spring XML's {@code <context:component-scan>} element.
*
* <p>One of {@link #basePackageClasses()}, {@link #basePackages()} or its alias
* {@link #value()} must be specified.
* {@link #value()} may be specified to define specific packages to scan. If specific
* packages are not defined scanning will occur from the package of the
* class with this annotation.
*
* <p>Note that the {@code <context:component-scan>} element has an
* {@code annotation-config} attribute, however this annotation does not. This is because

View File

@@ -65,7 +65,7 @@ class ComponentScanAnnotationParser {
}
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan) {
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
ClassPathBeanDefinitionScanner scanner =
new ClassPathBeanDefinitionScanner(registry, componentScan.getBoolean("useDefaultFilters"));
@@ -118,7 +118,7 @@ class ComponentScanAnnotationParser {
}
if (basePackages.isEmpty()) {
throw new IllegalStateException("At least one base package must be specified");
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
return scanner.doScan(basePackages.toArray(new String[]{}));

View File

@@ -210,7 +210,8 @@ class ConfigurationClassParser {
AnnotationAttributes componentScan = attributesFor(metadata, ComponentScan.class);
if (componentScan != null) {
// the config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan);
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, metadata.getClassName());
// check the set of scanned definitions for any further config classes and parse recursively if necessary
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {