Spring 3.X.X verwenden Ich habe 2 Dienste mit @Primary kommentiert und ich habe eine andere Konfigurationsklasse erstellt, wo ich eine "angepasste" Version eines der Dienste verwenden möchte.
Aus irgendeinem Grund ignoriere ich beim Debuggen der Konfigurationsklasse, dass ich sehe, dass es die richtigen Abhängigkeiten bekommt, aber wenn ich es benutzen will, hat es die falschen eingerichtet.
Ich finde es einfacher, mit Code zu erklären, hier ist ein Beispiel:
Schnittstelle Foo:
%Vor%Primäre Implementierung mit einer Standardnachricht hardcoded:
%Vor%Bar-Schnittstelle:
%Vor%Bar Standardimplementierung:
%Vor%So weit so gut, wenn ich eine Bar injizieren will, bekomme ich alles wie erwartet. Ich habe eine Konfiguration mit folgendem:
%Vor%Wenn ich eine readOnlyBar injizieren möchte, bekomme ich den Standard-Foo anstelle des hier eingestellten.
%Vor%Hat die Foo-Bean mit "fooDefaultMessage". Warum das? Wie kann ich sicherstellen, dass Spring die Bean verwendet, die ich in der @Configuration eingerichtet habe?
Vielen Dank im Voraus,
BEARBEITEN: Beachten Sie, dass das gleiche passiert, wenn Sie statt der readOnly () -Methode in der @Configuration-Klasse ein @Qualified-Argument übergeben. d.h.:
%Vor%Wenn ich stattdessen versuche, die Constructor-Abhängigkeitsinjektion zu verwenden, funktioniert alles so, wie ich es möchte / erwarte, aber leider kann ich das nicht verwenden.
Sie können @Autowired
nicht für eine Instanzvariable verwenden und diese in einer @Bean
-Methode wie Sie festlegen. Ein Teil des Frühlingslebenszyklus geht diesen Weg
Bean Definitionen gescannt = & gt; Bean Instanzen erstellt = & gt; Post-Prozessoren genannt = & gt; .....
In Ihrem Beispiel
%Vor% readOnlyBar
Bean wird erstellt, und weil readOnlyFoo()
von dieser Methode aufgerufen wird, wird auch readOnlyFoo
bean instanziiert. Bis zu diesem Punkt hat readOnlyBar
in seiner Instanzvariable readOnlyFoo
. Sobald die Bean instanziiert ist, wird AutowiredAnnotationBeanPostProcessor
aufgerufen, die die Klasse der Bean ( BarImpl
in diesem Fall) nach beliebigen @Autowired
-Anmerkungen für Instanzvariablen oder -methoden scannt. Es findet sie und versucht, die Beans in die entsprechenden Variablen zu injizieren, indem Feldinjektion oder Setter-Injektion verwendet wird (wo immer die @Autowired
Annotation vorhanden ist). In diesem Fall, da wir @Autowired
setter haben und die @Qualifier
-Anmerkung nicht angegeben haben, injiziert spring die @Primary
-Bohne, die die defaultFooMessage
-Bohne ist.
AFAIK, es gibt keine einfache Möglichkeit, im Frühjahr zu konfigurieren, damit @Bean
-Methoden Vorrang vor AutoWinding haben.
Durch die Instanziierung aller Beans mit @Bean
-Methoden wird das Problem behoben.
Normalerweise ist es besser, @Bean ("beanName") anstelle von zwei Anmerkungen zu verwenden: Bean und Qualifier. Und ich bin mir nicht sicher, ob Qualifier für die Benennung von Beans funktioniert. Wie auch immer, du solltest den Code in einem Stil schreiben. Wenn Sie also das Wertattribut in @Service-Annotation verwenden, sollten Sie das Wertattribut in @Bean Annotation verwenden.
Erstelle das Feld @Autowired List<Foo> allFoos
und betrachte es im Debug-Modus. Sie werden alle Foo Bohnen sehen, so dass Sie ihre Namen überprüfen können.
Wie @yaswanth in seiner Antwort darauf hingewiesen hat, bestand das Problem darin, dass die Eigenschaft foo
durch die Eigenschaftsinjektion nach der Erstellung der Bean überschrieben wurde.
Eine Möglichkeit, dies zu umgehen, ist die Verwendung der Konstruktorinjektion für BarImpl
anstelle von Property Injection. Das würde deinen Code wie ... aussehen lassen.
und deine Konfiguration wäre ...
%Vor%Als Nebenstrecke; Sie sollten auch sicherstellen, dass die Abhängigkeitsinjektion in Ihren Factory-Methoden verwendet wird, anstatt die Factory-Methode explizit aufzurufen, oder Sie erhalten mehrere Instanzen Ihrer Beans ...
Viel Glück mit Ihren zukünftigen Bemühungen!
Tags und Links java spring spring-bean