2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spring Frameworkの勉強ノート【その1】DIコンテナ

Last updated at Posted at 2018-09-25

はじめに

  • 今回の内容
    • Spring Frameworkの基盤の一つ、DIコンテナについて
    • 筆者の解釈による補完がいっぱいあるので、ご指摘あればぜひお願いします

題材

  • 以下のインターフェースと、それぞれの実装クラス。
    • ユーザの登録業務を行う UserService
    • 永続か処理を行う UserRep
    • パスワードのハッシュ化を行う PasswdEnc
  • クラス図を描くと以下のような感じ。

uml.png

依存性の注入(Dependency Injection, DI)

  • UserService クラスのコンストラクタが UserRepPasswdEnc 、それぞれの実装を引数にとると仮定する。
  • このとき UserServiceImpl クラスの使用例は以下の通り。
PasswdEnc passwdEnc = new PasswdEncImpl();
UserRep userRep = new UserRepImpl();
UserService userService = new UserServiceImpl(passwdEnc, userRep);
  • このように、あるクラスの初期化に必要となるコンポーネントを設定すること依存性の注入(Dependency Injection, DI) と呼ぶ。
  • DIを自動で行う基盤DIコンテナ と呼ぶ。
  • 「自動で行う」とはどういうことか?
  • (俺俺解釈) あるインターフェース型のインスタンスを初期化するときに、毎回呼びたい実装をあらかじめ設定しておくことで、インターフェース使用時の記述を楽にすること。

Bean定義ファイル

  • 「あらかじめ設定しておく」には...
    • @Configuration アノテーションを付与したクラス(Bean定義ファイル)にて定義を行う。
    • @Bean アノテーションを付与したコンポーネントを付与して、毎回呼びたい実装を指定する。
    • このようなコンポーネントは、他のコンポーネントの中に注入することもできる。
@Configuration
public class AppConfig{
  @Bean
  UserRep userRep(){
    return new UserRepImpl();
  }

  @Bean
  PasswdEnc passwdEnc(){
    return new PasswdEncImpl();
  }

  @Bean
  UserService userService(){
    return new UserServiceImpl(userRep(), passwdEnc());
  }
}
  • 上のようにあらかじめ設定しておけば、UserService インターフェース型の初期化はDIコンテナを経由して楽に実現できる。
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); 
// DIコンテナを生成

UserService userService = context.getBean(UserService.class) 
// DIコンテナを経由してあらかじめ設定した実装を取得
  • つまり、DIコンテナの利用は次の3つのフェイズに大別される。
    1. Bean定義にコンポーネントを登録する
    2. Bean定義からDIコンテナを生成する
    3. DIコテンナとBeanを指定して、意図した実装を呼び出す(ルックアップ

コンポーネントスキャン

  • Bean登録の方法には、Bean定義ファイルへの記述以外に、コンポーネントスキャンというものがある。
  • 実装クラスに直接 @Componentアノテーションを付与してBean登録し、他のコンポーネントから呼び出したいときは @Autowired アノテーションを付与する。
@Component // 自身をBean登録する
public class UserRepImpl implemente UserRep {
  // 省略
}
@Component // 自身をBean登録する
public class PasswdEncImpl implemente PasswdEnc {
  // 省略
}
@Component // 自身をBean登録するとともに...
public class UserServiceImpl implemente UserService {
  @Autowired // 他のBeanを注入する
  public UserServiceImpl(UserRep userRep, PasswdEnc passwdEnc)
}
  • @Autowiredデフォルトで対象の型が一致するBean をDIコンテナから探す。
  • コンポーネントスキャンを行う場合、以下のようにBean定義ファイルにてコンポーネントスキャン対象としたいパッケージを明示する必要がある。
@Configuration
@ComponentScan("com.example.hoge")
public class AppConfig{
}
  • ルックアップはBean定義ファイル利用時と同様。
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); 
// DIコンテナを生成

UserService userService = context.getBean(UserService.class) 
// DIコンテナを経由してあらかじめ設定した実装を取得

つづく

参考文献

  • 株式会社NTTデータ (2016) 『Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発』 翔泳社
2
3
0

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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?