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年以上。
 すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
 この記事に間違い等ありましたらぜひお知らせください。