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として自動配線するように設定する方法が必要になり、同時に@Qualifier
アノテーションで明示的に指定するときにJdbcDeviceDao
を使用できるようになります。
プロパティを設定してみました
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が自動配線候補としてマークされていなくても解決されます。*
これは、@Qualifier
アノテーションを使用してJdbcDeviceDao
を自動配線し、HibernateDeviceDao
をデフォルトBeanとして使用できることを意味すると解釈しました。ただし、サーバーの起動時に次のエラーメッセージが表示されるため、私の解釈は正しくないようです。
タイプの満たされていない依存関係[クラスcom.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]:少なくとも1つの一致するBeanが期待されます
修飾子でBeanを自動配線しようとしたクラスから来ています:
@Autowired
@Qualifier("jdbcDeviceDao")
skaffman'ssuggestion @Resourceアノテーションを試してみました。そのため、構成にはjdbcDeviceDaoのautowire-candidateがfalseに設定されており、jdbcDeviceDaoを使用するときは@Resourceアノテーション(@Qualifierの代わり)を使用して参照します。
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
Hibernate DAOクラスを @Primary
でマークすることをお勧めします(つまり、HibernateDeviceDao
で@Repository
を使用した場合):
@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao
これにより、他のBeanでautowire-candidate
を使用することなく、デフォルトの自動配線候補として選択されます。
また、@Autowired @Qualifier
を使用するよりも、特定のBeanを選択するために@Resource
を使用する方がエレガントであることがわかります。
@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
@Primary
についてはどうですか?
Beanを指定する必要があることを示します複数の候補が自動配線に適格な場合の設定単一値の依存関係。候補の中に正確に1つの「プライマリ」Beanが存在する場合、それは自動配線された値になります。このアノテーションは、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に注釈を付けることで簡単にスタブバージョンに置き換えることができる場合の統合テストにも最適です。
Spring 2.5では、@Primary
はありません。唯一の方法は@Qualifier
を使用することです。
The use of @Qualifier will solve the issue.
Explained as below example :
public interface PersonType {} // MasterInterface
@Component(value="1.2")
public class Person implements PersonType { //Bean implementing the interface
@Qualifier("1.2")
public void setPerson(PersonType person) {
this.person = person;
}
}
@Component(value="1.5")
public class NewPerson implements PersonType {
@Qualifier("1.5")
public void setNewPerson(PersonType newPerson) {
this.newPerson = newPerson;
}
}
Now get the application context object in any component class :
Object obj= BeanFactoryAnnotationUtils.qualifiedBeanOfType((ctx).getAutowireCapableBeanFactory(), PersonType.class, type);//type is the qualifier id
you can the object of class of which qualifier id is passed.