Sometimes we need to create different types of beans depending on certain conditions. Let's suppose we have a system in which we send notifications, and some clients of that system prefer notifications via email, while others prefer SMS notifications. In this case, we would need to inject a different bean for each client. To solve this problem, we can use the @ConditionalOnProperty annotation in Spring Boot.
What is @ConditionalOnProperty In Spring Boot?
@ConditionalOnProperty can read Spring Boot properties and, based on their values, determine whether the Bean will be created or not. This can be useful for solving the problem presented in the previous paragraph, or, for example, if we want to use a different Bean for the dev and prod environments.
Before we go on, feel free to have a look at my dev gift shop
How does @ConditionalOnProperty work in Spring Boot?
The operation of the annotation is quite intuitive:
@ConditionalOnProperty(name = "someName", havingValue = "true")
In the “name” attribute we put the property on whose value the creation of the Bean will depend and the “havingValue” attribute determines the expected value to create the Bean or not.
Example of using @ConditionalOnProperty in Spring Boot
The first thing we need to do is create a property in the application yml file.
configuration:
smsMessageEnabled: true
Now we can create an Interface and two classes that inherit from this interface.
@Service
@ConditionalOnProperty(name = "configuration.emailMessageEnabled", havingValue = "true")
public class EmailMessageServiceImpl implements MessageService{
private static final Logger log = LoggerFactory.getLogger(EmailMessageServiceImpl.class);
@Override
public void sendMessage(String message) {
log.info("Sending Email message: {}",message);
}
}
public interface MessageService {
void sendMessage(String message);
}
@Service
@ConditionalOnProperty(name = "configuration.smsMessageEnabled", havingValue = "true")
public class SmsMessageServiceImpl implements MessageService{
private static final Logger log = LoggerFactory.getLogger(SmsMessageServiceImpl.class);
@Override
public void sendMessage(String message) {
log.info("Sending SMS message: {}",message);
}
}
In the previous code we can see how we implemented the sendMessage method only with a log just for the purposes of the @ConditionalOnProperty example; in a real case this could be a call to some API.
In the @ConditionalOnProperty annotation we can see the reference to the property name that we wrote in the application yml file.
Now we have to test the code:
@SpringBootApplication
public class ConditionalOnProperty {
private static final Logger logger = LoggerFactory.getLogger(ConditionalOnProperty.class);
@Autowired
MessageService messageService;
public static void main(String[] args) {
SpringApplication.run(ConditionalOnProperty.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {
logger.info("Start");
messageService.sendMessage("Any Text ");
logger.info("Finish");
}
}
We will get an output like this:
We can see that we got the call of the method of the SmsMessageServiceImpl class which was the one we configured in the application.yml file
What did we learn?
Now we know that @ConditionalOnProperty helps us create beans based on defined conditions. Using it allows us to adapt our code to different environments, giving us greater flexibility in our application's behavior.
Top comments (0)