No cargar un Spring Bean cuando se establece un determinado perfil
-
02-01-2020 - |
Pregunta
Fondo: Entonces, tengo varios beans que interactúan con sistemas externos.Para el desarrollo, es conveniente burlarse de los sistemas externos y reemplazar los beans de interfaz con algunas implementaciones que produzcan respuestas más o menos estáticas.Entonces, lo que he estado haciendo es crear una interfaz, la implementación real y una implementación de código auxiliar como esta:
public interface ExternalService {
// ...
}
@Service
public class ExternalServiceImpl implements ExternalService {
// ...
}
@Service
@Primary
@Profile({"stub"})
public class StubExternalService implements ExternalService {
// ...
}
...y esto funciona muy bien:Si el perfil stub no está presente, el stub-bean no se carga en absoluto.Si está presente, reemplaza la implementación real debido a la anotación @Primary.
Problema: Ahora, sin embargo, he corrido por primera vez en una situación en la que tengo dos implementaciones reales de la misma interfaz.Uno de ellos se define como principal, pero el otro también se puede utilizar cargándolo desde el contexto de la aplicación.
Todavía me gustaría crear un servicio de código auxiliar para reemplazarlos a ambos, pero esta vez mi antigua forma de definir el código auxiliar como @Primary no funciona porque ya existe una implementación principal.Básicamente, lo que necesitaría es una forma de no cargar el bean principal cuando se configura el perfil de código auxiliar, pero no sé cómo hacerlo exactamente.Las búsquedas web u otras preguntas de Stack Overflow no parecen ayudar.
Solución
Resulta que la respuesta fue sorprendentemente simple:agregas un no operador (!
) delante del nombre del perfil:
@Service
@Primary
@Profile({"!stub"})
public class ExternalServiceImpl implements ExternalService {
// ...
}
De esta manera el frijol sólo se carga cuando el stub
-el perfil no está activo.El soporte para esta característica se agregó en Muelle 3,2 M1.
Sin embargo, hay una advertencia:Si tú escribes @Profile({"!stub", "foo"})
, la coma se trata como "o", no como "y".Entonces este bean de ejemplo se activaría si stub
no estaba activo o si foo
estaba activo.
Editar/Agregar: Spring 5.1 agregó soporte para un nuevo lenguaje de expresión para perfiles: !stub & foo
se activa cuando stub
no está activo y foo
está activo.¡Gran éxito!Incluso puedes mezclar y combinar ands y ors siempre que uses paréntesis: production & (us-east | eu-central)
.