DI(依存性注入)とSpringコンテナの仕組み 新人エンジニア向けにわかりやすく解説
こんにちは。ゆうせいです。
Spring Bootを使って開発していると、@Autowired をよく見かけますよね?
この @Autowired は DI(依存性注入: Dependency Injection) という仕組みの一部です。
では、DIとは何でしょうか?
また、Springコンテナ(Spring IoCコンテナ)がどのようにDIを実現しているのでしょうか?
今回は、これらの基本をわかりやすく解説します!
1. 依存性とは?
プログラムを書くとき、多くのクラスが他のクラスに依存して動作します。たとえば、以下のような UserService と UserRepository があったとします。
public class UserService {
private UserRepository userRepository;
public UserService() {
this.userRepository = new UserRepository();
}
public void getUser() {
userRepository.findUser();
}
}
public class UserRepository {
public void findUser() {
System.out.println("ユーザー情報を取得");
}
}
UserService の中で UserRepository のインスタンスを直接作成(new UserRepository())しています。
これは 「UserService は UserRepository に強く依存している」 状態です。
このように、あるクラスが別のクラスのインスタンスを直接生成することを 「依存関係がある」 と言います。
2. 依存性の問題点
上記の UserService にはいくつかの問題があります。
- 変更しにくい
UserRepositoryの実装を変えたくても、UserServiceのコードも変更しなければなりません。- たとえば、
UserRepositoryの代わりにMockUserRepositoryを使いたい場合、直接コードを書き換える必要があります。
- テストしにくい
UserServiceをテストしようとしてもUserRepositoryに依存しているため、テストが難しくなります。- たとえば、データベースにアクセスしないモック版の
UserRepositoryを使いたくても、new UserRepository()の部分が邪魔になります。
- コードの再利用がしにくい
UserRepositoryを他のクラスで使いたくても、UserServiceの中に組み込まれているため再利用しにくくなります。
3. 依存性注入(DI)とは?
依存性注入(Dependency Injection: DI)は、クラスの中で new して依存先のインスタンスを作るのではなく、外部から渡してもらう仕組み です。
UserService に UserRepository のインスタンスを コンストラクタ経由 で渡すように変更すると、次のようになります。
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void getUser() {
userRepository.findUser();
}
}
DIのポイント
UserServiceの中でUserRepositoryをnewしなくなった。- 代わりに コンストラクタで
UserRepositoryを受け取る ようになった。
こうすると、UserRepository の実装を簡単に変更できるようになります。
UserRepository userRepository = new UserRepository();
UserService userService = new UserService(userRepository);
これで、UserService は UserRepository に依存しつつも、具体的な実装には依存しない ようになりました。
これは 「依存の方向を逆転させる(Dependency Inversion)」 という考え方です。
4. SpringのDIコンテナ
では、Spring Boot ではどうやって DI を実現するのでしょうか?
Spring には 「Springコンテナ(Spring IoCコンテナ)」 という仕組みがあり、これが DI を自動で管理してくれます。
IoCコンテナとは?
IoC(Inversion of Control: 制御の反転)とは、オブジェクトの作成や管理を 「自分でやるのではなく、フレームワークに任せる」 という考え方です。
Spring Boot では、Springコンテナ(IoCコンテナ)がアプリケーション全体のオブジェクト(Bean)を管理します。
5. Spring Boot でのDIの実装
Spring Boot では、アノテーションを使って簡単にDIを実現できます。
① Beanの登録
SpringでDIを使うためには、クラスを Bean(Springが管理するオブジェクト) として登録する必要があります。
例えば、UserRepository をSpringの管理下に置くには @Repository を使います。
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
public void findUser() {
System.out.println("ユーザー情報を取得");
}
}
同様に、UserService を @Service でSpringに登録します。
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void getUser() {
userRepository.findUser();
}
}
② @Autowired による依存性注入
Spring Bootでは、@Autowired を使うと、依存するオブジェクトを自動で注入してくれます。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void getUser() {
userRepository.findUser();
}
}
Springコンテナが UserRepository のインスタンスを自動的に作り、UserService に渡してくれます。
これにより、new する必要がなくなり、依存関係がすっきり整理されます。
6. DIのメリット
Spring Boot の DI には次のようなメリットがあります。
- 疎結合になる
UserServiceはUserRepositoryの実装を直接知らなくてもよくなる。- 例えば
MockUserRepositoryに差し替えやすくなる。
- テストがしやすい
- 実際の
UserRepositoryの代わりに、モックオブジェクトを渡せるため、ユニットテストがしやすくなる。
- 実際の
- 管理が楽
- SpringコンテナがすべてのBeanを管理するので、開発者が
newする手間が省ける。
- SpringコンテナがすべてのBeanを管理するので、開発者が
まとめ
- DI(依存性注入) とは、オブジェクトの生成を外部から注入する仕組み。
- Springコンテナ(IoCコンテナ) がDIを自動で管理してくれる。
@Component/@Service/@Repositoryを使うと、Springが自動でオブジェクトを管理する。@Autowiredを使うと、依存関係を自動で注入してくれる。
これを理解すれば、Spring Boot の柔軟で効率的な開発ができるようになります!
次は「Springのスコープ」や「DIの種類(フィールドインジェクション vs コンストラクタインジェクション)」について学ぶと、さらに理解が深まりますよ!
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール
- 代表取締役
-
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。