In a Spring Boot Application I have a package with Application class like
@SpringBootApplication
class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application);
application.run(args);
}
}
which automatically has ComponentScan set up from that class's package by default. Then I have several subpackages each containing several component and service beans (using annotations). But for the purpose of reuse of this application for different use cases, I need to enable/disable all the components in some of the subpackages, preferably by a property.
That is I have subpackages like
org.example.app.provider.provider1
org.example.app.provider.provider2
Now, based on some property I would like to enable (scan for) beans in one of the packages, e.g.
provider1.enabled=true
I thought I could make ConditionalOnProperty on Configuration class work like that, but the problem is, that the beans are picked up by the default @SpringBootApplication component scan (i.e. the subpackage Configuration class does not override the top level one)
So I thought I would exclude the packages, but this adds more work (and knowledge) when a new provider package is needed (need to know in advance to add an explicit exclude for that package).
Is there any other way how to do this I can't figure out?
@ComponentScan - to enable component scanning, all the packages and subpackages will be auto-scanned which are under the root package on which @SpringBootApplication is applied. @EnableAutoConfiguration - to enable auto-configuration of the. classes bases on the jars added in classpath.
@ComponentScan tells Spring in which packages you have annotated classes which should be managed by Spring. Spring needs to know which packages contain spring beans, otherwise you would have to register each bean individually in(xml file). This is the use of @ComponentScan.
@Component and @ComponentScan are for different purposes. @Component indicates that a class might be a candidate for creating a bean. It's like putting a hand up. @ComponentScan is searching packages for Components.
The @ComponentScan annotation is used with the @Configuration annotation to tell Spring the packages to scan for annotated components. @ComponentScan also used to specify base packages and base package classes using thebasePackageClasses or basePackages attributes of @ComponentScan.
A Spring Configuration annotated with a @ConditionalOnProperty
would do just that:
@Configuration
@ComponentScan("org.example.app.provider.provider1")
@ConditionalOnProperty(name = "provider1.enabled", havingValue = "true")
public class Provider1Configuration {
}
@Configuration
@ComponentScan("org.example.app.provider.provider2")
@ConditionalOnProperty(name = "provider2.enabled", havingValue = "true")
public class Provider2Configuration {
}
org.example.app.provider.*
Now, all you need is to exclude the providers from Spring Boot Application (and let the CondtionalOnProperty
do its work). You can either:
For example, if the Spring Boot main is in org.example.app
, keep the @Configuration
in org.example.app
but the providers in org.example.providers
@Configuration
are in org.example.app
for example):SpringBootMain.java:
@SpringBootApplication
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = "org.example.app.provider.*"))
class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application);
application.run(args);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With