java

Springの@Autowiredでインターフェースを指定するのはなんでなの

Javaのアノテーションなんもわからん

Spring解体新書

速習系の書籍なので、書籍の通りやればWebアプリケーションは完成します。

完成するんですが、私の性格が災いしており、理解できないところがあるとそのままにできなくて一生進みません。

いま見ている本はセクション名の通りこれです。コンパクトにまとまっていて、手早くSpring Bootに触れるには、いい本であると思います。

なぜか@Autowiredで実装側のクラスでなくインターフェースを指定している

本の中では、Userオブジェクトに対するDB処理を実装するのに(MVCに則り?)層別に管理しています。

上から順番に、

  1. ユーザーの/homeへのリクエストを受け取って、
  2. HomeControllerがテンプレートエンジンを呼び出して、
  3. UserServiceが表示するUserに関する操作を受け持ち、
  4. UserDao@Autowiredされたinterfaceとして経由され、
  5. UserDaoJdbcImplに実際のDB操作が記述されており、
  6. DB(H2)のデータに到達する

みたいな感じです。

Springでは、アノテーションに@Autowiredをつけるとフレームワークがよしなにインスタンス管理をしてくれます。便利ですね。

このときSpringがやっていることに対する私の理解は、以下です。

  1. まずアプリケーションのビルドを開始します。
  2. Springのフレームワークがプロジェクト内のソースコードを捜査してアノテーションが付与されている変数やらクラスやらを認知します。
  3. メソッド等の呼び出しに応じてSpringがインスタンスの生成・管理を行います。
  4. インターフェースが@Autowiredされている場合、それを実装しているクラスのインスタンスが自動で紐づけられます。

よくわからないのは、なぜ実装しているクラスではなくインターフェース側に紐づけるかです。

実装しているクラスが単一の場合はわからんでもない

たとえば、今回の書籍の例ではUserService内に@Autowiredで規定されたUserDaoインターフェースがあります。

@Service
public class UserService {

    @Autowired
    @Qualifier("UserDaoJdbcImpl2")
    UserDao dao;
 // 以下ではダメなのか
 // UserDaoJdbcImpl2 dao;

このとき、@Qualifierがない場合はインターフェースを経由するメリットがありそうです。

具体的には、UserServiceのソースを書き換えずにUserDaoの実装側で内容をコントロールできます。

というのも、そのインターフェースを実装するクラスがひとつだけの場合、Springがそれをよしなに判別してその実装クラスに紐づけてくれるからです。

一方で、@Qualifierを付ける場合にはUserService内に実装側のクラス名が含まれてしまうため、インターフェースを経由していても結局UserService側の書き換えが必要になりそうです。

インターフェースを経由することで得られるメリットがピンと来ていません。

アノテーションの使い分けもよくわからない

@Componentとか@Repositoryとか、SpringでよしなにDIしてもらうためにアノテーションを付けますが、内容に違いはあるのでしょうか。

GitHubでRepositoryのソースを見てみましたが、どうやら@Repository@Componentのエイリアスとなっており、実装内容の違いがなさそうです。

もしそうであれば、DIのためのアノテーションは@Componentのみを使ってもよいのでしょうか?

私はまだJavaのソースの追い方がよくわかっていないので間違っているのかもしれませんが、このあたりの動作原理とか使う上での思想的な理由付けがいまいち理解できていません。

もしかしたら

時間がなくて追い切れていないですが、以前に読みかけだったドメイン駆動設計入門に思想面での理由付けなどが書かれていた記憶がおぼろげながらあります。

この本自体はC#をメインに紹介されていますが、どっちもSIerがよく使うオブジェクト指向言語という感じなので、いま読めば必要性がより身近に感じられるのかもしれないと思っています。

よくわからなくても、さらっとなめておくと必要な時にアクセスできるインデックスが自分の中にできるので、いま現在の必要性が薄いと感じる範囲でも積極的な学習は怠らないようにしたいな、と感じました。

いまはお気持ちですが

ちょっとお気持ちだけのオチがない記事ですが、謎が解けたらまた書きます。

もし読者にJavaとかオブジェクト指向に自信ニキの方がいたらTwitterのリプライでもDMでもいいので教えてください。よろしくお願いします。