@Autowired
代入されるBeanの決まり方
クラスで決まる (idやnameではなく)。
- マニュアルの4.9.3の中央あたりに「@Autowired is fundamentally about type-driven injection with optional semantic qualifiers」とある
@Autowired
HelloService helloService;
<bean class="springtest.jikken.HelloService" />
参照されるBeanはサブクラスでもよい?
@Autowired
HelloService helloService;
<bean class="springtest.jikken.HelloServiceForTest" />
クラスから決定される候補が2つ以上ある場合は、Qualifierで区別する。
<bean class="springtest.jikken.HelloService" />
<bean class="springtest.jikken.HelloServiceMock" >
<qualifier value="mock"/>
</bean>
@Autowired
@Qualifier("mock")
HelloService helloService; // HelloServiceMockが選択される
参照される側のBeanのidが、参照する側の変数名に一致すれば、そのBeanが選択されるらしい。
- マニュアルに説明が見当たらない
- 利用例: http://yamabuki.jp.net/2014/01/27/spring%E3%81%A7di2/
<bean id="helloService" class="springtest.jikken.HelloService" />
<bean id="helloService2" class="springtest.jikken.HelloServiceMock" />
@Autowired
HelloService helloService2; // HelloServiceMockが代入される
- 参照する側が上記のとおりのとき、XMLの定義が次のとおりだと、エラーになる。helloService2に対応する定義がなく、クラスHelloServiceからBeanを選択しようとすると候補が1つにしぼれないため。
<bean id="helloService" class="springtest.jikken.HelloService" /> <bean id="helloServiceMock" class="springtest.jikken.HelloServiceMock" />
なお、代入されるBeanを名前で決めたい場合は、@Autowiredの代わりに、@Resource(javax.annotation.Resource)を使う。
代入されるBeanの決まり方(component-scanとの組み合わせ)
次のケースを考える。
XMLに次のとおりcomponent-scanの指定があり、
<context:annotation-config/> <!-- @Autowired や @Configuration などのアノテーション指定を有効にする。 -->
<context:component-scan base-package="springtest.jikken"/>
Bean側には@Componentをつけて管理対象であることを宣言するとする。
package springtest.jikken;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("singleton")
public class HelloService {
テスト用にHelloServiceMockを作る。こちらには@Componentをつけない。
package springtest.jikken;
public class HelloServiceMock extends HelloService {
Beanを参照する側は次のとおりとする。
@Autowired
HelloService helloService;
helloServiceには通常時はHelloServiceを代入し、テスト時にHelloServiceMockを代入するようにしたい。
- XMLにbeanの定義をしない場合
- HelloServiceが代入される。
- XMLに次を定義
<bean class="springtest.jikken.HelloServiceMock" />
- 依然としてHelloServiceが代入される。型HelloServiceから決まるBeanの候補は、component-scanで検出されるHelloServiceとbeanタグで指定したHelloServiceMockの2つがあるにもかかわらず、エラーにはならない(不可解)。
- XMLに次を定義
<bean id="helloService" class="springtest.jikken.HelloServiceMock" />
- HelloServiceMockが代入される。参照側の変数名と同じ名前をidに指定しているため。
- XMLに次を定義
<bean class="springtest.jikken.HelloServiceMock" primary="true" />
- HelloServiceMockが代入される。primary="true"を指定することで、component-scanで検出のクラスより優先されるらしい。