En ocaciones necesitamos crear diferentes tipos de Beans dependiendo de una ciertas condiciones. Supongamos que tenemos un sistema en que tenemos envios de notificaciones y algunos clientes de ese sistema prefieren que las notificaciones sean por email y otros clientes prefieren que sean por sms. En este caso deberiamos inyectar un bean diferente para cada cliente.Para resolver este problema nos podemos ayudar de la anotacion @ConditionalOnProperty en Spring Boot.
¿Que es @ConditionalOnProperty en Spring Boot?
@ConditionalOnProperty puede leer propiedades de Spring Boot y con base en su valor determinaar si el Bean se creara o no. Esto puede ser util para solventar el problema presentado en el parrafo anterior o por ejemplo si queremos usar un Bean diferente para el ambiente dev y prod.
¿Como funciona @ConditionalOnProperty en Spring Boot?
El funcionamiento de la anotacion es bastante intuitivo:
|
1 |
@ConditionalOnProperty(name = "", havingValue = "true") |
En el atributo “name” ponemos la propiedad de cuyo valor dependera el la creación del Bean y el atributo “havingValue” determina el valor esperado para crear o no el Bean.
Ejemplo del uso de @ConditionalOnProperty en Spring Boot
Lo primero que debemos de hacer es crear una la propiedad en el archivo application yml.
|
1 2 |
configuration: smsMessageEnabled: true |
Ahora podemos crear una Interfaz y dos clases que hereden de esta interfaz.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
@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); } } |
|
1 2 3 |
public interface MessageService { void sendMessage(String message); } |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
@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); } } |
En el Código anterior podemos ver como implementamos el metodo sendMessage solo con un log solo para efectos del ejemplo de @ConditionalOnProperty en un caso real esto podria ser un llamado al algun API.
En la anotacion @ConditionalOnProperty podemos ver la referencia al nombre de la propiedad que escribimos en el archivo application yml.
Ahora nos queda probar el codigo:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@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"); } } |
Obtendremos una salida como esta:
|
1 2 3 |
Start Sending SMS message: Any Text Finish |
Podemos ver que obtivimos el llamado del metodo de la clase SmsMessageServiceImpl que fue el que configuramos en el archivo application.yml
¿Que aprendimos?
Ahora sabemos que @ConditionalOnProperty nos ayuda a crear beans basado en que se cumplan condiciones que podemos definir. Su uso nos permite adaptar nuestro codigo a diferentes entornos brindandonos asi una mayor flexibilidad en comportamiento de nuestra aplicación.