146

バックグラウンド:

Spring 2.5/Java/Tomcat アプリケーションがあります。アプリケーション全体で多くの場所で使用される次の Bean があります。

public class HibernateDeviceDao implements DeviceDao

そして、新しい次の Bean :

public class JdbcDeviceDao implements DeviceDao

最初の Bean はそのように構成されています (パッケージ内のすべての Bean が含まれています)。

<context:component-scan base-package="com.initech.service.dao.hibernate" />

2 番目の (新しい) Bean は個別に構成されます

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
    <property name="dataSource" ref="jdbcDataSource">
</bean>

これにより、(もちろん) サーバーの起動時に例外が発生します。

ネストされた例外は org.springframework.beans.factory.NoSuchBeanDefinitionException: タイプ [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] の一意の Bean が定義されていません: 単一の一致する Bean が予想されますが、2 が見つかりました: [deviceDao, jdbcDeviceDao]

このように Bean を自動配線しようとしているクラスから

@Autowired
private DeviceDao hibernateDevicDao;

同じインターフェースを実装する 2 つの Bean があるためです。

質問:

そのようにBeanを構成することは可能ですか?

1.HibernateDeviceDaoすでにオートワイヤーされている既存のクラスを変更する必要はありません。

2.次のように 2 番目の (新しい) Bean を引き続き使用できます。

@Autowired
@Qualifier("jdbcDeviceDao")

HibernateDeviceDaoつまり、Bean をデフォルトの Bean として自動配線するように構成する方法が必要であり、同時にアノテーションJdbcDeviceDaoで明示的に指定するときに を使用できるようにする必要があります@Qualifier

私がすでに試したこと:

プロパティを設定してみました

autowire-candidate="false"

JdbcDeviceDao の Bean 構成:

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
    <property name="dataSource" ref="jdbcDataSource"/>
</bean>

Springのドキュメントにそう書かれているので

別の Bean の自動配線要件を満たすために一致する候補を探すときに、この Bean を考慮する必要があるかどうかを示します。これは、指定された Bean がオートワイヤー候補としてマークされていなくても解決される、名前による明示的な参照には影響しないことに注意してください。

これは、注釈をJdbcDeviceDao使用して自動配線し、デフォルトの Beanを使用できることを意味すると解釈しました。ただし、サーバーの起動時に次のエラーメッセージが表示されるため、私の解釈は明らかに正しくありませんでした。@QualifierHibernateDeviceDao

タイプ [class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao] の満たされていない依存関係: 少なくとも 1 つの一致する Bean が必要です

修飾子を使用して Bean を自動配線しようとしたクラスから来ています。

@Autowired
@Qualifier("jdbcDeviceDao")

解決:

@Resource アノテーションを試すというskaffman の提案はうまくいきました。そのため、構成では jdbcDeviceDao に対して autowire-candidate が false に設定されており、jdbcDeviceDao を使用する場合は、@Resource アノテーション (@Qualifier の代わりに) を使用して参照します。

@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
4

5 に答える 5

135

Hibernate DAO クラスを でマークすることをお勧めします ( on@Primaryを使用したと仮定します):@RepositoryHibernateDeviceDao

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

autowire-candidateこのようにして、他の Beanを必要とせずに、デフォルトの自動配線候補として選択されます。

また、 を使用するよりも、特定の Bean を選択するため@Autowired @Qualifierに使用する方がエレガントだと思います。@Resource

@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
于 2012-05-10T12:35:52.893 に答える
39

どう@Primaryですか?

複数の候補が単一値の依存関係を自動配線する資格がある場合、Bean を優先する必要があることを示します。候補の中に 'primary' Bean が 1 つだけ存在する場合、それが autowired 値になります。このアノテーションは、Spring XMLの<bean>要素の属性と意味的に同等です。primary

@Primary
public class HibernateDeviceDao implements DeviceDao

または、Jdbc バージョンをデフォルトで使用する場合:

<bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">

@Primaryまた、アノテーションを付けることで本番 Bean をスタブ バージョンに簡単に置き換えることができるため、統合テストにも最適です。

于 2012-05-10T12:37:01.490 に答える
9

Spring 2.5 の場合はありません@Primary。唯一の方法は、を使用すること@Qualifierです。

于 2012-05-10T12:46:50.970 に答える