@Target(value=TYPE)
@Retention(value=RUNTIME)
@Configuration
@ComponentScan(excludeFilters=)
public @interface ComponentScanExcludingConfigurationForTest
@ConfigurationForTest
annotation instead of the standard @Configuration
annotation. This is meant as a solution for a rather common problem that arises when your application
uses @ComponentScan to find @Services, @Components etc, and have integration tests that reside in "src/test/java",
but has the same package as the application code (to allow for package access). In the tests, you might want to
include the entire application's Spring configuration, thus you include the same @ComponentScan. The problem now is
that since all the test classes are included on the classpath when running a test, and at the same time reside in the
same package structure, the component scan will pick up all tests' @Configuration classes too. This is absolutely not
what you wanted - in particular if e.g. two different tests tries to set up two different variants of a mock
collaborating Mats endpoint (that is, an application-external service that this application communicates with):
You'll end up trying to take up both variants at the same time, and since they have the same endpointId, Mats will
refuse this.
If you employ this annotation (@ComponentScanExcludingConfigurationForTest) - or set up the same "excludeFilters" as
this annotation does - you will not include any configuration classes that are annotated with
@ConfigurationForTest
instead of the ordinary @Configuration. However, each test will
still pick up its own inner static @ConfigurationForTest class(es).
A test class employing @ConfigurationForTest would look something like this:
@MatsTestProfile // <- If you employ the JmsSpringConnectionFactoryProducer's logic to handle JMS ConnectionFactory @RunWith(SpringRunner.class) public class IntegrationTestClass { @ConfigurationForTest @Import(ApplicationSpringConfigurationClass_Using_ComponentScanExcludingConfigurationForTest.class) public static class InnerStaticConfigurationClassForTest { // @Bean definitions // @MatsMapping definitions } // @Inject'ed fields.. // @Test-methods.. }
If you want to do the exclusion on your own, you can use the standard @ComponentScan, making sure you include this excludeFilters property:
@ComponentScan(excludeFilters = { @Filter(type = FilterType.ANNOTATION, value = ConfigurationForTest.class) })
This class has @AliasFor all properties that Spring 4.x has on @ComponentScan. If new properties arrive later which you want to use, you will have to do the exclusion on your own.
NOTICE: An alternative way to achieve the same effect is to annotate the integration test class with @ContextConfiguration, pointing to both the application's Spring setup, and also the configuration class residing within the test class - but where the test's configuration class is not annotated with @Configuration. Such an integration test class would look something like this:
@MatsTestProfile // <- If you employ the JmsSpringConnectionFactoryProducer's logic to handle JMS ConnectionFactory @RunWith(SpringRunner.class) @ContextConfiguration(classes = { ApplicationSpringConfigurationClass_Using_ComponentScan.class, InnerStaticConfigurationClassForTest.class }) public class IntegrationTestClass { // Notice how this configuration class is NOT annotated with @Configuration, to avoid being picked up by // application's @ComponentScan public static class InnerStaticConfigurationClassForTest { // @Bean definitions // @MatsMapping definitions } // @Inject'ed fields.. // @Test-methods.. }
Modifier and Type | Optional Element and Description |
---|---|
java.lang.Class<?>[] |
basePackageClasses
Type-safe alternative to
basePackages() for specifying the packages to scan for annotated components. |
java.lang.String[] |
basePackages
Base packages to scan for annotated components.
|
org.springframework.context.annotation.ComponentScan.Filter[] |
excludeFilters
Specifies which types are not eligible for component scanning.
|
org.springframework.context.annotation.ComponentScan.Filter[] |
includeFilters
Specifies which types are eligible for component scanning.
|
boolean |
lazyInit
Specify whether scanned beans should be registered for lazy initialization.
|
java.lang.Class<? extends org.springframework.beans.factory.support.BeanNameGenerator> |
nameGenerator
The
BeanNameGenerator class to be used for naming detected components within the Spring container. |
java.lang.String |
resourcePattern
Controls the class files eligible for component detection.
|
org.springframework.context.annotation.ScopedProxyMode |
scopedProxy
Indicates whether proxies should be generated for detected components, which may be necessary when using scopes
in a proxy-style fashion.
|
java.lang.Class<? extends org.springframework.context.annotation.ScopeMetadataResolver> |
scopeResolver
The
ScopeMetadataResolver to be used for resolving the scope of detected components. |
boolean |
useDefaultFilters
Indicates whether automatic detection of classes annotated with
@Component @Repository ,
@Service , or @Controller should be enabled. |
java.lang.String[] |
value
Alias for
basePackages() . |
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="value") public abstract java.lang.String[] value
basePackages()
.
Allows for more concise annotation declarations if no other attributes are needed — for example,
@ComponentScan("org.my.pkg")
instead of @ComponentScan(basePackages = "org.my.pkg")
.
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="basePackages") public abstract java.lang.String[] basePackages
value()
is an alias for (and mutually exclusive with) this attribute.
Use basePackageClasses()
for a type-safe alternative to String-based package names.
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="basePackageClasses") public abstract java.lang.Class<?>[] basePackageClasses
basePackages()
for specifying the packages to scan for annotated components. The
package of each class specified will be scanned.
Consider creating a special no-op marker class or interface in each package that serves no purpose other than being referenced by this attribute.
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="nameGenerator") public abstract java.lang.Class<? extends org.springframework.beans.factory.support.BeanNameGenerator> nameGenerator
BeanNameGenerator
class to be used for naming detected components within the Spring container.
The default value of the BeanNameGenerator
interface itself indicates that the scanner used to process
this @ComponentScan
annotation should use its inherited bean name generator, e.g. the default
AnnotationBeanNameGenerator
or any custom instance supplied to the application context at bootstrap time.
AnnotationConfigApplicationContext.setBeanNameGenerator(BeanNameGenerator)
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="scopeResolver") public abstract java.lang.Class<? extends org.springframework.context.annotation.ScopeMetadataResolver> scopeResolver
ScopeMetadataResolver
to be used for resolving the scope of detected components.@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="scopedProxy") public abstract org.springframework.context.annotation.ScopedProxyMode scopedProxy
The default is defer to the default behavior of the component scanner used to execute the actual scan.
Note that setting this attribute overrides any value set for scopeResolver()
.
ClassPathBeanDefinitionScanner.setScopedProxyMode(ScopedProxyMode)
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="resourcePattern") public abstract java.lang.String resourcePattern
Consider use of includeFilters()
and excludeFilters()
for a more flexible approach.
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="useDefaultFilters") public abstract boolean useDefaultFilters
@Component
@Repository
,
@Service
, or @Controller
should be enabled.@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="includeFilters") public abstract org.springframework.context.annotation.ComponentScan.Filter[] includeFilters
Further narrows the set of candidate components from everything in basePackages()
to everything in the
base packages that matches the given filter or filters.
Note that these filters will be applied in addition to the default filters, if specified. Any type under the
specified base packages which matches a given filter will be included, even if it does not match the default
filters (i.e. is not annotated with @Component
).
resourcePattern()
,
useDefaultFilters()
@AliasFor(annotation=org.springframework.context.annotation.ComponentScan.class, attribute="excludeFilters") public abstract org.springframework.context.annotation.ComponentScan.Filter[] excludeFilters
resourcePattern()