1. ホーム
  2. java

[解決済み] 同じインタフェースを実装する2つのビーンを自動配線する - 自動配線するデフォルトのビーンを設定する方法は?

2022-05-09 15:34:06

質問

背景

Spring 2.5/Java/Tomcatのアプリケーションを持っています。次のようなビーンがあり、アプリケーションのあちこちで使用されています。

public class HibernateDeviceDao implements DeviceDao

と、新しい次のビーンです。

public class JdbcDeviceDao implements DeviceDao

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

<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.NoSuchBeanDefinitionException です。com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] 型のユニークな Bean が定義されていません: 1 つの一致する Bean を期待しましたが、2 つ見つかりました: [deviceDao, jdbcDeviceDao].

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

@Autowired
private DeviceDao hibernateDevicDao;

というのも、同じインタフェースを実装しているビーンが2つあるからです。

質問です。

ビーンズを構成して、以下のようにすることは可能ですか?

1. 既存のクラスを変更する必要はなく、すでに HibernateDeviceDao オートワイヤード

2. が、2つ目の(新しい)ビーンをこのように使用することができます。

@Autowired
@Qualifier("jdbcDeviceDao")

を設定する方法が必要です。 HibernateDeviceDao ビーンを自動配線されるデフォルトのビーンとして使用し、同時に 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を満たすために一致する候補を探す。 自動配線要件 ただし、これは明示的な 名前による参照は、たとえ指定された ビーンは、自動配線候補としてマークされていません。

というのは、まだオートワイアが可能だと解釈しました。 JdbcDeviceDao を使用して @Qualifier アノテーションを使用し HibernateDeviceDao をデフォルトのビーンとして使用します。しかし、どうやら私の解釈は正しくなかったようで、この結果、サーバを起動すると以下のようなエラーメッセージが表示されます。

タイプ [class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao] の Unsatisfied dependency: expecting at least 1 matching bean

というクラスから来るので、ビーンを修飾子で自動配線してみました。

@Autowired
@Qualifier("jdbcDeviceDao")

解決策

スカッフマンズ 提案 を使って@Resourceアノテーションを試してみるとうまくいきました。つまり、jdbcDeviceDaoのautowire-candidateをfalseに設定し、jdbcDeviceDaoを使うときは(@Qualifierではなく)@Resourceアノテーションで参照する構成になっています。

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

解決方法は?

私は、Hibernate DAO クラスを、以下のようにマークすることを提案します。 @Primary を使用したと仮定すると、そのようなことはありません。 @RepositoryHibernateDeviceDao ):

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

こうすることで、デフォルトのオートワイヤ候補として選択されるようになるので、以下の作業は必要ありません。 autowire-candidate を他のビーンに追加します。

また @Autowired @Qualifier を使用する方がよりエレガントだと思います。 @Resource を特定のビーンを選ぶために使用します。

@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;