LoginSignup
30
42

More than 5 years have passed since last update.

DI (依存性の注入)っていったいなんだ?

Posted at

※以下の内容は社内研修での勉強内容を転載したものとなります。


DIとか本を読んでもよく分からなかったので調べました。

DI

DI = Dependency Injection

  • 「依存性の注入」とよく訳される。(けどなんだかいまいちよく分からずスッキリしない、、、)
  • dependencyを英訳すると「A dependency is an object that can be used (a service).」。つまりDIとは、「依存性の注入」じゃなくて、「オブジェクトの注入」ということらしい。(こっちの方がなんとなくわかるかも。)

そもそも依存しているとはどのような状態?

  • 「クラスAをコンパイルするためには(あるいは正しく動かすためには)、クラスBが既に出来上がってないとだめ」という状態のこと。
  • こういう状態にあることを「クラスAはクラスBに依存している」という。

依存性が高いと困ること

  • 単体テストがしづらい。
  • 依存しているクラスBが壊れるとクラスAも使えないし、どちらに原因があるのか特定しづらい。
  • そこで「依存性をクラスの外で定義すればいいんじゃないの?」という発想が生まれてくる。

つまりDI=依存性(オブジェクト)の注入を行うとは?

  • クラスAがクラスBに依存しているという情報を、クラスAの外で定義して外からクラスAのインスタンスに突っ込んであげるということ。
  • 簡単に言うと「依存性(オブジェクト)を外から注入したい」ということ。
  • これが実現されると、クラスBがなくてもクラスAを動かせるようになる。つまり粗結合になり、テストしやすくなる。

参考
要するに DI って何なのという話
DI・DIコンテナ、ちゃんと理解出来てる・・?

DIコンテナ

  • 単純に言えば、DIを実現するためのフレームワーク(箱、入れ物)。
  • DIを自動で行い、インスタンスを組み立ててくれる基盤。
  • ただし、DIコンテナがないとDIが実現できないわけではない。

DIを実現するための仕組み

以下のように定義をおこなっていくことでDIが実現される

ApplicationContextとBean定義

  • Spring FrameworkではApplicationContextがDIコンテナの役割を担う。
DIコンテナからインスタンスを取り出す実装例
ApplicationContext context = new AnnotationConfigurationContext(AppConfig.class); 
UserService userService = context.getBean(Userservice.class); 

①コンフィギュレーションクラスを渡してDIコンテナを生成。
②DIコンテナからUserServiceインスタンスを取得。

  • ApplicationContextはBeanFactory(※1)の有する機能以外に以下の機能を有する。
    • URL やファイルのようなリソースへのアクセス
    • ApplicationListener インタフェースを実装したビーンへのイベントの伝播
    • 複数のコンテキストをロード可能

(※1)
・Spring の中でもっとも基本となる重要なパッケージは org.springframework.beans パッケージと org.springframework.context パッケージ。
・Dependency Injection の基本的な機能はこれらのパッケージが提供している。
・これらのパッケージのなかでも JavaBeans を管理する実際のコンテナとして中心的な役割を果たすのが BeanFactory。
・BeanFactory は依存関係が記述された定義ファイルを元に JavaBeans の生成・管理を行う。

  • 実装例のAppConfigクラスは、DIコンテナに対する設定ファイル。
  • 「Java Config」とも呼ばれる。
  • Java Configクラスの実装例についてはp.16~17参照

ApplicationContextを使ったアプリケーションでは

  • DiコンテナにConfigurationを使用して、コンポーネントを登録し、ApplicationContextインターフェースを通じてDIコンテナからBeanを取得する。
  • DIコンテナに登録するコンポーネントを「Bean」、Configurationのことを「Bean定義」と呼ぶ。
  • DIコンテナからBeanを取得することを「ルックアップ」と呼ぶ。

参考
2. BeanFactory と Bean 定義

代表的なBean定義(Configuration)

① JavaベースConfiguration
@Configurationアノテーションが付与されたJavaクラスに@Beanアノテーションが付与されたメソッドを使用し、Beanを定義する方法。
② XMLベースConfiguration
→ XMLファイル中の要素のclass属性にFQCN(完全修飾クラス名)を記述し、や要素を使ってインジェクションの設定を行う方法。
(内部構造が分かりやすいがエラーがわかりにくい)
③ アノテーションベースConfiguration
@Componentなどのまあーカーアノテーションが付与されたクラスを「コンポーネントスキャン」という手段を用いて自動的にDIコンテナに登録する方法。

インジェクションの種類

① セッターインジェクション
→ コンポーネントがセッターを持つ場合、そのセッターの引数に対して依存するコンポーネントを注入する方法。
② コンストラクタインジェクション
→ コンストラクタに依存コンポーネントを直接設定する方法。(javaベース)
→ 要素で参照するコンポーネントを設定する方法。(XMLベース)
→ コンストラクタに@Autowired を付与する方法。(アノテーションベース)
③ フィールドインジェクション
→ インジェクションしたいフィールドに@Autowired を付与する方法。
→ コンストラクタやセッターは不要で省略可。

30
42
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
42