Springを使った開発では、コンテナに登録したいクラスに@Component、依存性を注入するときに@Autowiredというアノテーションを使用しますが、似たようなアノテーションとして@Namedと@Injectというものがありますが、どちらを使うべきなのでしょうか?
@AutowiredはSpring独自アノテーション
今ではJavaの言語仕様としてCDI (Contexts and Dependency Injection)という名称でDIの仕様が定義されています。
しかし昔のJavaにはDIはなく、Spring Frameworkが独自にDIを開発して普及したのが始まりです。
そして@Autowiredは、Springがもともと提供していたアノテーションでした。
@InjectはJava標準アノテーション
その後、SpringのDIをベースにした概念がJavaの標準APIに含まれました。この仕様は「JSR-330」という名前で呼ばれています。
@InjectはそのJSR-330で決められたアノテーションで、javax.injectというパッケージにあることからもJavaの標準APIであることがわかります。
Springならどちらのアノテーションでも動く
Spring Frameworkを使っていれば、どちらのアノテーションでも問題なく動きます。
それは、Springが独自アノテーションに加えて、JSR-330のアノテーションも処理するように対応しているからです。
当然ですが、Spring以外のDIを使う場合は、Spring独自の@Autowiredは動作しません。
僕はSpringのアノテーションを好んで使用
Springを使っていれば@Injectでも@Autowiredでも全く同じ動作をするため、「ならばどちらのアノテーションを使うべきか」という質問が出てきます。
「やっぱり標準を使った方がいいのかな」
と思うこともありますが、僕個人的にはずっとSpringのものを使ってきたので、それをそのまま使い続けています。
これはチームや会社によると思いますが、僕のいる環境はサーバーサイドの開発がほとんどで、メンバーもSpringの方が馴染みある人が多いように感じるので、「いつも通り」のやり方をした方がいいかなと思っています。
Spring Frameworkを使わない環境や、将来使わなくなる可能性がある環境であれば標準APIを使った方がいいと思いますが、今のところそういう気配は全く感じていないので、Springにロックインされたままで問題はないかなと思っています。
仮にSpring以外への移行があったとしても、アノテーションの書き換えだけならばスクリプトを書けば一括で変換できますしね。
一方、Springを前提としていない開発や、将来Springを使わなくなる可能性が見えているのなら今のうちから標準のアノテーションを使うべきだと思います。
JSRとは
ちなみにJSRというのはJava Specification Request(Java仕様リクエスト)というもので、言語仕様に対する仕様拡張や変更要求(提案)となっていて、330というのは採用されたJSRの番号となっています。
しかしJSR-330では「インジェクションはこう動作するべき」という仕様を規定するだけで、実装は提供しません。
これによって、仕様(API)に準拠さえしていれば、どのベンダーでもDIの実装を提供することができますし、(理論上は)アプリケーションのコードを変更することなく実装のみを切り替えるということも可能です。
JSR-330はDI関連の仕様ですが、別の似たような例を挙げると
- Hibernateが広めたORMフレームワークがJPA (Java Persistence API)に
- Spring Batchで提供されたバッチフレームワークがjBatchに
といったものがあります。
これは「先進的なベンダーが作ったものを標準化して吸い上げて奪う」ということでなく、オープンソースプロジェクトも多く関わるJavaコミュニティ全体で決められています。
DIに関しては、Springは独自のDI実装に加えて、それをJSR-330のDIにも対応させていますし、上で挙げたHibernateもJPA実装を、Spring BatchもJBatchの実装を提供しています。
OracleがJava(Sun)を買収したときは、Oracleデータベースのようにクセと商売色が強いものになっていくという危惧もありましたが、この時代にオープン化、標準化、Javaコミュニティプロセスなど、いい意味での変化があったと個人的には感じています。