@Autowired
、@Inject
、@Resource
について、共通的な動きとしては、何れも自動でフィールドにbeanをインジェクションすることです。今回はそれらの違いについて、検証してみます。
-
@Resource
⇨javax.annotation
-
@Inject
⇨javax.inject
-
@Autowired
⇨org.springframework.bean.factory
#事前準備
以下のクラスを用意する。
・インタフェースクラスPrint
・インタフェースクラスPrint
の実装クラスHelloWorldPrintImp
・インタフェースクラスPrint
の実装クラスHelloMoonPrintImp
public interface Print {
public void print();
}
@Component
public class HelloWorldPrintImp implements Print {
@Override
public void print() {
System.out.println("Hello World");
}
}
@Component
public class HelloMoonPrintImp implements Print {
@Override
public void print() {
System.out.println("Hello Moon");
}
}
#検証1
@Autowired
private Print print;
@Inject
private Print print;
@Resource
private Print print;
上記のケースは、何れも例外NoUniqueBeanDefinitionException
が発生した。
インタフェースクラスPrint
の実装クラスのbeanがユニックでないのが原因である。
#検証2
@Autowired
private Print helloWorldPrintImp;
@Inject
private Print helloWorldPrintImp;
@Resource
private Print helloWorldPrintImp;
インジェクション対象のフィルド名を@Component
のクラス名と一致すればに、検証1の例外を回避し、上記何れも正常にインジェクションできる。
実行結果は以下の通りです。
@Autowired
:Hello World
@Inject
:Hello World
@Resource
:Hello World
#検証3
@Autowired
@Qualifier("helloWorldPrintImp")
private Print print;
@Inject
@Qualifier("helloWorldPrintImp")
private Print print;
@Resource
@Qualifier("helloWorldPrintImp")
private Print print;
@Qualifier("name")
を上記のアノテーションと併用することで、インジェクション対象bean名を指定でき、検証1の例外も同様に回避する。
実行結果は以下の通りです。
@Autowired
:Hello World
@Inject
:Hello World
@Resource
:Hello World
#検証4
@Autowired
@Qualifier("helloMoonPrintImp")
private Print helloWorldPrintImp;
@Inject
@Qualifier("helloMoonPrintImp")
private Print helloWorldPrintImp;
@Resource
@Qualifier("helloMoonPrintImp")
private Print helloWorldPrintImp;
フィルド名=コンポーネントクラス名、且つ@Qualifier
で別のコンポーネントを指定する場合、@Autowired
と@Inject
の動きは一緒であり、@Qualifier
で指定するコンポーネントがインジェクションされている。
@Resource
は@Qualifier
で指定のコンポーネントを無視し、フィルド名と一致のコンポーネントがインジェクションされている。
実行結果は以下の通りです。
@Autowired
:Hello Moon
@Inject
:Hello Moon
@Resource
:Hello World
また、@Resource(name="name")
でコンポーネント名を指定できる。
@Resource(name="helloMoonPrintImp")
private Print helloWorldPrintImp;
その場合に、nameで指定されるコンポーネントがインジェクションされる。
実行結果は以下の通りです。
@Resource
:Hello Moon
#結論
タイプ一致の場合に、インジェクションの優先順位:
@Autowired
と@Inject
1.Qualifier指定のコンポーネント
2.フィルド名と一致のコンポーネント
@Resource
1.@Resource(name="name")
で指定のコンポーネント
2.フィルド名と一致のコンポーネント
3.Qualifier指定のコンポーネント