web-dev-qa-db-ja.com

同じインターフェースを実装する2つのBeanの自動配線-デフォルトBeanを自動配線に設定する方法は?

バックグラウンド:

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;
121
simon

Hibernate DAOクラスを @Primary でマークすることをお勧めします(つまり、HibernateDeviceDao@Repositoryを使用した場合):

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

これにより、他のBeanでautowire-candidateを使用することなく、デフォルトの自動配線候補として選択されます。

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

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

@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に注釈を付けることで簡単にスタブバージョンに置き換えることができる場合の統合テストにも最適です。

34

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

7
blang
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.
0
Sandeep Jain