La anotación Spring @ConditionalOnProperty

1. Información general

En este breve tutorial, vamos a arrojar luz sobre el propósito principal de la anotación @ConditionalOnProperty .

Primero, comenzaremos con algunos antecedentes sobre qué es @ConditionalOnProperty . Luego, veremos algunos ejemplos prácticos para ayudar a comprender cómo funciona y qué características trae.

2. El propósito de @ConditionalOnProperty

Por lo general, al desarrollar aplicaciones basadas en Spring, es posible que necesitemos crear algunos beans condicionalmente en función de la presencia y el valor de una propiedad de configuración .

Por ejemplo, es posible que queramos registrar un bean DataSource para que apunte a una base de datos de producción o de prueba dependiendo de si establecemos un valor de propiedad en "prod" o "test".

Afortunadamente, lograrlo no es tan difícil como podría parecer a primera vista. El marco de Spring proporciona la anotación @ConditionalOnProperty precisamente para este propósito.

En resumen, @ConditionalOnProperty habilita el registro de beans solo si una propiedad del entorno está presente y tiene un valor específico. De forma predeterminada, la propiedad especificada debe estar definida y no es igual a falsa .

Ahora que estamos familiarizados con el propósito de la anotación @ConditionalOnProperty , profundicemos para ver cómo funciona.

3. La anotación @ConditionalOnProperty en la práctica

Para ejemplificar el uso de @ConditionalOnProperty, desarrollaremos un sistema de notificación básico. Para simplificar las cosas por ahora, supongamos que queremos enviar notificaciones por correo electrónico.

Primero, necesitaremos crear un servicio simple para enviar un mensaje de notificación. Por ejemplo, considere la interfaz NotificationSender :

public interface NotificationSender { String send(String message); }

A continuación, proporcionemos una implementación de la interfaz NotificationSender para enviar nuestros correos electrónicos:

public class EmailNotification implements NotificationSender { @Override public String send(String message) { return "Email Notification: " + message; } }

Ahora, veamos cómo hacer uso de la anotación @ConditionalOnProperty . Configuremos el bean NotificationSender de tal manera que solo se cargue si se define la propiedad notification.service :

@Bean(name = "emailNotification") @ConditionalOnProperty(prefix = "notification", name = "service") public NotificationSender notificationSender() { return new EmailNotification(); }

Como podemos ver, los atributos de prefijo y nombre se utilizan para denotar la propiedad de configuración que se debe verificar .

Finalmente, necesitamos agregar la última pieza faltante del rompecabezas. Definamos nuestra propiedad personalizada en el archivo application.properties :

notification.service=email

4. Configuración avanzada

Como ya hemos aprendido, la anotación @ConditionalOnProperty nos permite registrar beans de forma condicional dependiendo de la presencia de una propiedad de configuración.

Sin embargo, podemos hacer más que eso con esta anotación . Entonces, ¡exploremos!

Supongamos que queremos agregar otro servicio de notificación, por ejemplo, un servicio que nos permitirá enviar notificaciones por SMS.

Para hacer eso, necesitamos crear otra implementación de NotificationSender :

public class SmsNotification implements NotificationSender { @Override public String send(String message) { return "SMS Notification: " + message; } }

Ya que tenemos dos implementaciones, veamos cómo podemos usar @ConditionalOnProperty para cargar el bean NotificationSender correcto condicionalmente.

Para este propósito, la anotación proporciona el atributo havingValue . Muy interesante, se define el valor de que una propiedad debe tener a fin de que un grano específico que se añade al recipiente de primavera .

Ahora, especifiquemos bajo qué condición queremos registrar la implementación de SmsNotification en el contexto:

@Bean(name = "smsNotification") @ConditionalOnProperty(prefix = "notification", name = "service", havingValue = "sms") public NotificationSender notificationSender2() { return new SmsNotification(); }

Con la ayuda del atributo havingValue , dejamos en claro que queremos cargar SmsNotification solo cuando notification.service esté configurado en sms .

Vale la pena mencionar que @ConditionalOnProperty tiene otro atributo llamado matchIfMissing . Este atributo especifica si la condición debe coincidir en caso de que la propiedad no esté disponible .

Ahora, juntemos todas las piezas y escribamos un caso de prueba simple para confirmar que todo funciona como se esperaba:

@Test public void whenValueSetToEmail_thenCreateEmailNotification() { this.contextRunner.withPropertyValues("notification.service=email") .withUserConfiguration(NotificationConfig.class) .run(context -> { assertThat(context).hasBean("emailNotification"); NotificationSender notificationSender = context.getBean(EmailNotification.class); assertThat(notificationSender.send("Hello From Baeldung!")).isEqualTo("Email Notification: Hello From Baeldung!"); assertThat(context).doesNotHaveBean("smsNotification"); }); }

5. Conclusión

En este breve tutorial, destacamos el propósito de usar la anotación @ConditionalOnProperty . Luego, mostramos, a través de un ejemplo práctico, cómo usarlo para cargar Spring beans de forma condicional.

Como siempre, el código fuente completo de este tutorial está disponible en GitHub.