Spring is a very popular open source framework that can be used to build any kind of java application. Spring Bean is an object, which is created, managed and destroyed in Spring Container. We can inject an object into the Spring Container through the metadata(either xml or annotation) without manually creating and managing instances of them. This is called inversion of control.
There may be situations where we have to inject a Bean based on a certain condition. Some example cases are
- Customizing the application
- Running it on cloud / on premises
- Using the same app with multiple environments
1. Example case.
Our Spring application needs to support both cloud and on premise deployments. Cloud version will work as a normal web application with the embedded Tomcat and on premise version will be deployed on JBoss as a war file. We have a service named FileService.java having different implementation logic depending on the deployment.
2. Configuration class.
Let’s create a configuration class named AppConfig.java that contains Bean definitions for the FileService.java implementations.
Here the Bean will be injected after checking an application property against a given value. The matchIfMissing = true property will make the expression match when the application property is missing.
We can use expressions as well like below. Other that these, there are multiple predefined annotations for conditional bean loading. Some of them are,
- @ConditionalOnJava — Java version checking.
- @ConditioalOnWarDeployment — For war deployments.
- @ConditionalOnWebApplication — For web applications.
- @ConditionalOnNotWebApplication — For none web applications.
4. Custom conditions.
There may be situations where it will be much convenient and readable to put the condition check in a separate file. To do so we have to customize the @Conditional annotation. Depending on the return value of matches method, the bean will be loaded / discarded.
If needed, we can add more complex logic that use information about the current application context (ConditionContext) or the annotated class (AnnotatedTypeMetadata).
Then we can add it at AppConfig.java as below.
5. Using Annotation on the component.
Without using the conditional inside the @Configuration class, we can put it in the component class. There the condition will be checked and the bean will be loaded if it passes.
6. Running the application.
Do the implementation using any of the above methods according to your requirement and run the application. The corresponding bean will be loaded according to the condition. This can be verified by the logs / debugging the application. You can find the complete code here.