Hintergrund:
Ich habe eine Spring 2.5 / Java / Tomcat-Anwendung. Es gibt die folgende Bohne, die an vielen Stellen in der gesamten Anwendung verwendet wird
public class HibernateDeviceDao implements DeviceDao
und die folgende Bohne, die neu ist:
public class JdbcDeviceDao implements DeviceDao
Die erste Bean ist so konfiguriert (alle Beans im Paket sind enthalten).
<context:component-scan base-package="com.initech.service.dao.hibernate" />
Die zweite (neue) Bean wird separat konfiguriert
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
<property name="dataSource" ref="jdbcDataSource">
</bean>
Dies führt (natürlich) zu einer Ausnahme beim Starten des Servers:
verschachtelte Ausnahme ist org.springframework.beans.factory.NoSuchBeanDefinitionException: Es ist keine eindeutige Bean vom Typ [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] definiert: erwartete einzelne übereinstimmende Bean, aber gefunden 2: [deviceDao, jdbcDeviceDao]
von einer Klasse, die versucht, die Bohne so automatisch zu verdrahten
@Autowired
private DeviceDao hibernateDevicDao;
weil es zwei Beans gibt, die dieselbe Schnittstelle implementieren.
Die Frage:
Ist es möglich, die Beans so zu konfigurieren?
1. Ich muss keine Änderungen an vorhandenen Klassen vornehmen, die bereits über eine HibernateDeviceDao
automatische Verdrahtung verfügen
2. die zweite (neue) Bohne immer noch so verwenden können:
@Autowired
@Qualifier("jdbcDeviceDao")
Das heißt, ich würde eine Möglichkeit benötigen, die HibernateDeviceDao
Bean als Standard-Bean für die automatische Verdrahtung zu konfigurieren und gleichzeitig die Verwendung eines zu ermöglichen, JdbcDeviceDao
wenn dies explizit mit der @Qualifier
Anmerkung angegeben wird.
Was ich schon versucht habe:
Ich habe versucht, die Eigenschaft festzulegen
autowire-candidate="false"
in der Bean-Konfiguration für JdbcDeviceDao:
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
weil die Spring-Dokumentation das sagt
Gibt an, ob diese Bean berücksichtigt werden soll, wenn nach passenden Kandidaten gesucht wird, um die Autowiring-Anforderungen einer anderen Bean zu erfüllen. Beachten Sie, dass dies keine Auswirkungen auf explizite Verweise nach Namen hat, die auch dann aufgelöst werden, wenn die angegebene Bean nicht als Autowire-Kandidat markiert ist. *
was ich so interpretierte, dass ich JdbcDeviceDao
mit der @Qualifier
Annotation immer noch automatisch verdrahten und die HibernateDeviceDao
als Standard-Bean haben konnte. Anscheinend war meine Interpretation jedoch nicht korrekt, da dies beim Starten des Servers zu der folgenden Fehlermeldung führt:
Unbefriedigte Abhängigkeit vom Typ [Klasse com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: mindestens 1 übereinstimmende Bean erwartet
Ich komme aus der Klasse, in der ich versucht habe, die Bohne mit einem Qualifier automatisch zu verdrahten:
@Autowired
@Qualifier("jdbcDeviceDao")
Lösung:
Der Vorschlag von skaffman, die @ Resource-Annotation auszuprobieren, hat funktioniert. In der Konfiguration ist der Autowire-Kandidat für jdbcDeviceDao auf false gesetzt, und wenn ich jdbcDeviceDao verwende, verweise ich mit der Annotation @Resource (anstelle von @Qualifier) darauf:
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
quelle
Antworten:
Ich würde vorschlagen , die Hibernate DAO Klasse mit Markierung
@Primary
, dh (vorausgesetzt , Sie verwenden@Repository
aufHibernateDeviceDao
):Auf diese Weise wird es als Standard-Autowire-Kandidat ausgewählt, ohne dass dies für
autowire-candidate
die andere Bean erforderlich ist .Anstatt es zu verwenden
@Autowired @Qualifier
, finde ich es auch eleganter,@Resource
bestimmte Bohnen zu pflücken, d. H.quelle
@Resource
Anmerkung aus, wie ich auch vorgeschlagen habe.@Resource
und@Qualifier
, abgesehen von der Tatsache, dass der erstere relativ neuer ist als der letztere?Was ist mit
@Primary
?Oder wenn Sie möchten, dass Ihre Jdbc-Version standardmäßig verwendet wird:
@Primary
eignet sich auch hervorragend für Integrationstests, wenn Sie die Produktions-Bean durch Anmerkungen einfach durch eine gestubbte Version ersetzen können.quelle
primary=""
Attribut war früher verfügbar.HibernateDeviceDao
Deklarieren Sie einfach in XML und schließen Sie es vom Scannen von Komponenten / Anmerkungen aus.Für Spring 2.5 gibt es keine
@Primary
. Der einzige Weg ist zu verwenden@Qualifier
.quelle
quelle
Der Grund, warum @Resource (name = "{Name Ihrer untergeordneten Klasse}") funktioniert, @Autowired jedoch manchmal nicht funktioniert, liegt in der unterschiedlichen Übereinstimmungssequenz
Übereinstimmende Reihenfolge von @Autowire-
Typ, Qualifizierer, Name
Übereinstimmende Reihenfolge von @ Ressourcenname
, Typ, Qualifizierer
Die ausführlichere Erklärung finden Sie hier:
Inject and Resource- und Autowired-Annotationen
In diesem Fall verwirrt eine andere untergeordnete Klasse, die von der übergeordneten Klasse oder Schnittstelle geerbt wurde, @Autowire, da sie vom selben Typ sind. Da @Resource Name als erste übereinstimmende Priorität verwendet, funktioniert dies.
quelle