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

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
@@ -21,9 +21,7 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
import java.io.IOException;
@@ -47,6 +45,7 @@ import example.scannable.DefaultNamedComponent;
import example.scannable.FooService;
import example.scannable.MessageBean;
import example.scannable.ScopedProxyTestBean;
import example.scannable_implicitbasepackage.ComponentScanAnnotatedConfigWithImplicitBasePackage;
import example.scannable_scoped.CustomScopeAnnotationBean;
import example.scannable_scoped.MyScope;
@@ -93,6 +92,18 @@ public class ComponentScanAnnotationIntegrationTests {
ctx.containsBean("fooServiceImpl"), is(true));
}
@Test
public void viaContextRegistration_FromPackageOfConfigClass() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ComponentScanAnnotatedConfigWithImplicitBasePackage.class);
ctx.refresh();
ctx.getBean(ComponentScanAnnotatedConfigWithImplicitBasePackage.class);
assertThat("config class bean not found", ctx.containsBeanDefinition("componentScanAnnotatedConfigWithImplicitBasePackage"), is(true));
assertThat("@ComponentScan annotated @Configuration class registered directly against " +
"AnnotationConfigApplicationContext did not trigger component scanning as expected",
ctx.containsBean("scannedComponent"), is(true));
}
@Test
public void viaBeanRegistration() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -110,18 +121,6 @@ public class ComponentScanAnnotationIntegrationTests {
ctx.containsBean("fooServiceImpl"), is(true));
}
@Test
public void invalidComponentScanDeclaration_noPackagesSpecified() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ComponentScanWithNoPackagesConfig.class);
try {
ctx.refresh();
fail("Expected exception when parsing @ComponentScan definition that declares no packages");
} catch (IllegalStateException ex) {
assertThat(ex.getMessage(), containsString("At least one base package must be specified"));
}
}
@Test
public void withCustomBeanNameGenerator() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();