Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional spring bean creation

I have a question about Spring annotation configurations. I have a bean:

@Bean 
public ObservationWebSocketClient observationWebSocketClient(){
    log.info("creating web socket connection...");
    return new ObservationWebSocketClient();
}

and I have a property file:

@Autowired
Environment env;

In the property file I want to have a special boolean property

createWebsocket=true/false

which signs whether a bean ObservationWebSocketClient should be created. If property value is false I don't want to establish web socket connection at all.

Is there any technical possibility to realize this?

like image 759
user2957954 Avatar asked Apr 24 '15 09:04

user2957954


People also ask

What are conditional beans in Spring?

Why do we need Conditional Beans? A Spring application context contains an object graph that makes up all the beans that our application needs at runtime. Spring's @Conditional annotation allows us to define conditions under which a certain bean is included into that object graph.

How do you use a Spring conditional bean?

Conditions based on a Bean definition are present in Spring Application context. Conditions based on a Bean object are present in Spring Application context. Conditions based on some or all Bean properties values. Conditions based on some Resources are present in current Spring Application Context or not.

What is conditional on missing bean?

Annotation Type ConditionalOnMissingBean. @Conditional that only matches when no beans meeting the specified requirements are already contained in the BeanFactory . None of the requirements must be met for the condition to match and the requirements do not have to be met by the same bean.

How do I remove Spring beans based on specific conditions?

In Spring Boot, you can use the @ConditionalOnProperty annotation to enable or disable a particular bean based on the presence of a property. This is very useful if you want to provide optional features to your microservice. And that's it. Your optionalClass bean should resolve to null when you specify mybean.


3 Answers

Though I've not used this functionality, it appears that you can do this with spring 4's @Conditional annotation.

First, create a Condition class, in which the ConditionContext has access to the Environment:

public class MyCondition implements Condition {     @Override     public boolean matches(ConditionContext context,                             AnnotatedTypeMetadata metadata) {         Environment env = context.getEnvironment();         return null != env                 && "true".equals(env.getProperty("createWebSocket"));     } } 

Then annotate your bean:

@Bean @Conditional(MyCondition.class) public ObservationWebSocketClient observationWebSocketClient(){     log.info("creating web socket connection...");     return new ObservationWebSocketClient(); } 

edit The spring-boot annotation @ConditionalOnProperty has implemented this generically; the source code for the Condition used to evaluate it is available on github here for those interested. If you find yourself often needing this funcitonality, using a similar implementation would be advisable rather than making lots of custom Condition implementations.

like image 173
beerbajay Avatar answered Oct 02 '22 09:10

beerbajay


Annotate your bean method with @ConditionalOnProperty("createWebSocket").

Note that Spring Boot offers a number of useful conditions prepackaged.

like image 38
chrylis -cautiouslyoptimistic- Avatar answered Oct 02 '22 11:10

chrylis -cautiouslyoptimistic-


For Spring Boot 2+ you can simply use:

@Profile("prod")
or
@Profile({"prod","stg"})

That will allow you to filter the desired profile/profiles, for production or staging and for the underlying Bean using that annotation it only will be loaded by Springboot when you set the variable spring.profiles.active is equals to "prod" and ("prod" or "stg"). That variable can be set on O.S. environment variables or using command line, such as -Dspring.profiles.active=prod.

like image 20
rod.dinis Avatar answered Oct 02 '22 10:10

rod.dinis