exclude @Component from @ComponentScan
The configuration seem alright, except that you should use excludeFilters
instead of excludes
:
@Configuration @EnableSpringConfigured
@ComponentScan(basePackages = {"com.example"}, excludeFilters={
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})
public class MySpringConfiguration {}
Exclude a particular class from Spring Component scan while writing Spring Integration Test
You can make use of @Conditional
as shown below.
- In
application.properties
introduce a property saykafka.enabled
. - Annotate the
OrderReceiveEventConfiguration
with@Conditional(PropertyCondition.class)
- Depending on
kafka.enabled
value viz.true
(for normal run) orfalse
(for testing) theOrderReceiveEventConfiguration
will be picked up or ignored respectively without changing the code.
Let know in comments in case any more information is required.
Except main @conditional
annotation there are set of similar annotation to be used for different cases.
Class conditions
The @ConditionalOnClass
and @ConditionalOnMissingClass
annotations allows configuration to be included based on the presence or absence of specific classes.
E.g. when OObjectDatabaseTx.class
is added to dependencies and there is no OrientWebConfigurer
bean we create the configurer.
@Bean
@ConditionalOnWebApplication
@ConditionalOnClass(OObjectDatabaseTx.class)
@ConditionalOnMissingBean(OrientWebConfigurer.class)
public OrientWebConfigurer orientWebConfigurer() {
return new OrientWebConfigurer();
}
Bean conditions
The @ConditionalOnBean
and @ConditionalOnMissingBean
annotations allow a bean to be included based on the presence or absence of specific beans. You can use the value attribute to specify beans by type, or name to specify beans by name. The search attribute allows you to limit the ApplicationContext
hierarchy that should be considered when searching for beans.
See the example above when we check whether there is no defined bean.
Property conditions
The @ConditionalOnProperty
annotation allows configuration to be included based on a Spring Environment property. Use the prefix and name attributes to specify the property that should be checked. By default any property that exists and is not equal to false
will be matched. You can also create more advanced checks using the havingValue
and matchIfMissing
attributes.
@ConditionalOnProperty(value='somebean.enabled', matchIfMissing = true, havingValue="yes")
@Bean
public SomeBean someBean(){
}
Resource conditions
The @ConditionalOnResource
annotation allows configuration to be included only when a specific resource is present.
@ConditionalOnResource(resources = "classpath:init-db.sql")
Web application conditions
The @ConditionalOnWebApplication
and @ConditionalOnNotWebApplication
annotations allow configuration to be included depending on whether the application is a 'web application'.
@Configuration
@ConditionalOnWebApplication
public class MyWebMvcAutoConfiguration {...}
SpEL expression conditions
The @ConditionalOnExpression
annotation allows configuration to be included based on the result of a SpEL expression.
@ConditionalOnExpression("${rest.security.enabled}==false")
Spring @ComponentScan exclude/include filters
Basically @ControllerAdvice
annotated classes are ordered, which means that if Spring internals find an @ExceptionHandler
which accepts the thrown exception, it will use that one and stop.
When having multiple classes it is possible to set the bean priority with @Order
(for example). Annotating the ServiceException
containing class with @Order
made it working.
Also, based on this feature request https://jira.spring.io/browse/SPR-8881 we can specify multiple classes on one @Filter
annotation, no need to split them in multiple @Filter
(s).
Spring boot ComponentScan excludeFIlters not excluding
Each component scan does filtering individually. While you exclude Starter.class
from SimpleTestConfig
, SimpleTestConfig
initializes Application
, which does it's own @ComponentScan
without excluding Starter
.
The clean way of using ComponentScan is for each ComponentScan to scan separate packages, that way each filter works fine. When 2 separate ComponentScans scan the same package (as in your tests), this does not work.
One way to trick this is to provide a mock Starter
bean:
import org.springframework.boot.test.mock.mockito.MockBean;
public class SimpleTest {
@MockBean
private Starter myTestBean;
...
}
Spring will use that mock instead of the real class, thus the @PostConstruct
method will not be called.
Other common solutions:
- Do not directly use
Application.class
in any unit test - Use Spring profile and annotations such as
@Profile("!TEST")
on theStarter
class - Use a spring Boot
@ConditionalOn...
annotation on theStarter
class
Define Spring beans in library and exclude them from ComponentScan
There might be some ways to exclude the library package from project A or B's component scan without explicitly stating that the package is to be excluded.
Use a different package root for your library
The most straightforward option is to use a different package root for the library than the project uses. Since the @SpringBootApplication
annotation is meta-annotated with @ComponentScan
, if @ComponentScan
's attributes basePackageClasses
or basePackages
have not been specified, the package name of the annotated class is used as root package to use for component scanning (source):
Configures component scanning directives for use with @Configuration classes. Provides support parallel with Spring XML's context:component-scan element. Either basePackageClasses() or basePackages() (or its alias 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 that declares this annotation.
For instance, if a @SpringBootApplication
annotated root class is located in package com.example.somepackage
:
package com.example.somepackage;
@SpringBootApplication
public class DemoApplication {
...
}
The base package root com.example.somepackage
will be used as the root for component scanning. Using com.example.library
instead of com.example.somepackage.library
should exclude the library from being included in the component scanning.
Make use of ConditionalOn
annotations in the Library
If the method above doesn't work and the configuration is still automatically included during component scanning, a slightly less invasive way when compared to using profiles is adding @ConditionalOnX
annotations to your configuration class, such as:
ConditionalOnProperty
@Configuration
@ConditionalOnProperty(prefix = "yourlibrary", name = "enabled", havingValue="true")
The projects relying on the library will now need to include the property yourlibrary.enabled=true
.
More info on the several @ConditionalOn
annotations can be found here.
Exclude class from ComponentScan of SpringBoot
You could work with profiles.
Annotate your integration test with @ActiveProfiles("test")
and your component that should be loaded for integration tests with @Profile("test")
and the Components that should not be loaded for integration tests with @Profile("!test")
Related Topics
Adding Chartpanel to Jtabbedpane Using JPAnel
Filtering Database Rows with Spring-Data-JPA and Spring-Mvc
Spring Qualifier and Property Placeholder
Generics:List<? Extends Animal> Is Same as List<Animal>
Double Calculation Producing Odd Result
Using Jaxb to Cross Reference Xmlids from Two Xml Files
Java Lib or App to Convert CSV to Xml File
Java: Starting a New Thread in a Constructor
Deserialize JSON to Arraylist<Pojo> Using Jackson
Multiple Input in Joptionpane.Showinputdialog
How to Resize Jlabel Imageicon
Adding an Http Header to the Request in a Servlet Filter
In a Switch Statement, Why Are All the Cases Being Executed
What Is the Point of the Class Option[T]
How to Disable or Bypass Hardware Graphics Acceleration(Prism) in Javafx
Java.Lang.Illegalstateexception: Not on Fx Application Thread; Currentthread = Thread-4