Es wird kein Spring-Bean geladen, wenn ein bestimmtes Profil festgelegt ist
-
02-01-2020 - |
Frage
Hintergrund: Ich habe also mehrere Beans, die externe Systeme verbinden.Für die Entwicklung ist es praktisch, die externen Systeme zu verspotten und die Schnittstellen-Beans durch einige Implementierungen zu ersetzen, die mehr oder weniger statische Antworten erzeugen.Ich habe also eine Schnittstelle, die eigentliche Implementierung und eine Stub-Implementierung wie folgt erstellt:
public interface ExternalService {
// ...
}
@Service
public class ExternalServiceImpl implements ExternalService {
// ...
}
@Service
@Primary
@Profile({"stub"})
public class StubExternalService implements ExternalService {
// ...
}
...und das funktioniert super:Wenn das Stub-Profil nicht vorhanden ist, wird das Stub-Bean überhaupt nicht geladen.Wenn es vorhanden ist, ersetzt es aufgrund der @Primary-Annotation die tatsächliche Implementierung.
Problem: Jetzt bin ich jedoch zum ersten Mal in einer Situation, in der ich tatsächlich zwei echte Implementierungen derselben Schnittstelle habe.Einer davon ist als primär definiert, der andere kann jedoch auch verwendet werden, indem er aus dem Anwendungskontext geladen wird.
Ich würde immer noch gerne einen Stub-Dienst erstellen, um beide zu ersetzen, aber dieses Mal funktioniert meine alte Methode, den Stub als @Primary zu definieren, nicht, da es bereits eine primäre Implementierung gibt.Grundsätzlich bräuchte ich eine Möglichkeit, die primäre Bean nicht zu laden, wenn das Stub-Profil festgelegt ist, aber ich weiß nicht, wie ich das genau machen soll.Websuchen oder andere Fragen zum Stapelüberlauf scheinen nicht zu helfen.
Lösung
Es stellte sich heraus, dass die Antwort überraschend einfach war:Sie fügen einen Nicht-Operator hinzu (!
) vor dem Profilnamen:
@Service
@Primary
@Profile({"!stub"})
public class ExternalServiceImpl implements ExternalService {
// ...
}
Auf diese Weise wird die Bean nur geladen, wenn die stub
-profile ist nicht aktiv.Die Unterstützung für diese Funktion wurde hinzugefügt Feder 3,2 M1.
Es gibt jedoch eine Einschränkung:wenn du schreibst @Profile({"!stub", "foo"})
, wird das Komma als „oder“ und nicht als „und“ behandelt.Diese Beispiel-Bean würde also in beiden Fällen aktiviert werden stub
war nicht aktiv oder wenn foo
war aktiv.
Bearbeiten/Hinzufügen: Spring 5.1 fügte eine Unterstützung für a hinzu Neue Ausdruckssprache für Profile: !stub & foo
wird aktiviert, wenn stub
ist nicht aktiv und foo
ist aktiv.Großer Erfolg!Sie können sogar Ands und Ors kombinieren und kombinieren, vorausgesetzt, Sie verwenden Klammern: production & (us-east | eu-central)
.