2018년 3월 13일 화요일

@Autowired、@Inject、@Resourceの違いについての検証

@Autowired、@Inject、@Resourceの違いについての検証
Java
spring
 この記事は最終更新日から1年以上が経過しています。
@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指定のコンポーネント

댓글 없음:

댓글 쓰기