この記事に書いてあること
Springを使っていて、インタフェースを使ってノリノリでコーディングしていると、以下のエラーにぶつかることがあります。
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'XXXXXXXX' available: expected single matching bean but found 2: xxxxx,xxxxxx
上記の例だと、インスタンス化の候補が2つあるからどっちを使えばいいのか分からないよというエラーです。
これを解決します。この記事なんかで書いている方式で実装しようとするとぶつかることが多い課題だと思います。
前提
- Spring Framework 4.xx
- java8
原因
以下のようなクラス構成を見てください。
このような関連のクラスがあった時、SampleController内で以下のようなコードを書くと、NoUniqueBeanDefinitionException: No qualifying bean of type 'XXXXXXXX'が発生します。
public class SampleController {
@Autowired
private SampleLogic sampleLogicImpl;
public void execute() {
// TODO 自動生成されたコンストラクター・スタブ
}
}
4行目に問題があります。
クラス図の通り、インタフェースに紐づいた実態は2つありますから、この書き方ではどちらを使ってインスタンス化すればいいかわからないよ!と怒っているわけです。
簡単に回避することができます。
対策
@Qualifierを使います。これは、使用するインスタンスを名前で指定するものです。
public class SampleController {
@Autowired
@Qualifier("sampleLoginImpl2")
private SampleLogic sampleLogicImpl;
public void execute() {
// TODO 自動生成されたコンストラクター・スタブ
}
}
実装クラス側では@componentのアノテーションに引数で名前を渡してやります。SampleLogicImpl1と2は以下のようになります。
@Component(value="sampleLogicImple")
public class SampleLogicImpl implements SampleLogic {
//省略
}
@Component(value="sampleLogicImple2")
public class SampleLogicImpl2 implements SampleLogic {
//省略
}
これで、SpringのBean空間に指定の名前で登録されますから、実装クラスがいくつあってもAutowired時にFrameworkが混乱することもありません。
※複数の実装クラスをListで取ったりすることもできるのですが、どこで役に立つんですかね。Storategyとかで刺さることは多そうですね。個人的には利用シーンに遭遇したことはありません。