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

@@ -0,0 +1,27 @@
/*
* 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.
* 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 example.scannable_implicitbasepackage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author Phillip Webb
*/
@Configuration
@ComponentScan
public class ComponentScanAnnotatedConfigWithImplicitBasePackage {
}

View File

@@ -0,0 +1,26 @@
/*
* 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.
* 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 example.scannable_implicitbasepackage;
import org.springframework.stereotype.Component;
/**
* @author Phillip Webb
*/
@Component
public class ScannedComponent {
}

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();