Spring

Last-modified: 2014-09-11 (木) 00:25:13

@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が選択されるらしい。

    <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を代入するようにしたい。

  1. XMLにbeanの定義をしない場合
    • HelloServiceが代入される。
  2. XMLに次を定義
        <bean class="springtest.jikken.HelloServiceMock" />
    • 依然としてHelloServiceが代入される。型HelloServiceから決まるBeanの候補は、component-scanで検出されるHelloServiceとbeanタグで指定したHelloServiceMockの2つがあるにもかかわらず、エラーにはならない(不可解)。
  3. XMLに次を定義
        <bean id="helloService" class="springtest.jikken.HelloServiceMock" />
    • HelloServiceMockが代入される。参照側の変数名と同じ名前をidに指定しているため。
  4. XMLに次を定義
        <bean class="springtest.jikken.HelloServiceMock" primary="true"  />
    • HelloServiceMockが代入される。primary="true"を指定することで、component-scanで検出のクラスより優先されるらしい。