【Java初心者向け】Spring FrameworkでのDI(依存性注入)の使い方を丁寧に解説!
こんにちは。ゆうせいです。
今回はSpring FrameworkのDI(Dependency Injection:依存性注入)について、初心者の方にもわかりやすく解説します。
特に注目するのは、よく使われるアノテーション:
@Autowired
これを正しく使いこなせると、Spring開発がグッと楽になりますよ!
そもそもDIとは?
DI(Dependency Injection:依存性注入)とは?
「クラスが必要とする依存オブジェクトを、自分で new しないで、外部から注入してもらうこと」です。
たとえばこういうこと:
// NG:自分でnewしている
UserService service = new UserService(new UserRepository());
// OK:外からUserRepositoryを渡す(注入する)
UserRepository repository = ...;
UserService service = new UserService(repository);
依存関係を外から注入する設計にすることで、
- テストしやすくなる
- 実装を切り替えやすくなる
などのメリットが生まれます。
SpringがDIしてくれるしくみ
Springでは、「DIコンテナ」が必要なオブジェクトを自動的に生成・注入してくれます。
そのために使うのが、以下のアノテーションたち:
アノテーション | 役割 |
---|---|
@Component | Springに「このクラスを管理してね」と伝える |
@Autowired | Springに「このフィールドやコンストラクタに依存を注入してね」と伝える |
@Service , @Repository , @Controller | @Component の特化型。役割別の明示 |
実際に使ってみよう!(コード例)
① リポジトリクラスを作る
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
public String findUserName() {
return "Yamada Taro";
}
}
ここで @Repository
をつけると、SpringがこのクラスをDIの対象として登録してくれます。
② サービスクラスで注入を受け取る
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 showUserName() {
System.out.println(userRepository.findUserName());
}
}
ここでは、コンストラクタに @Autowired
をつけることで、Springが自動で UserRepository
を注入してくれます。
@Autowired
の使い方3パターン
方法 | 書き方 | 特徴 |
---|---|---|
フィールド注入 | @Autowired をフィールドにつける | 簡単だがテストがやや不便 |
セッター注入 | セッターメソッドに @Autowired | 任意のタイミングで差し替え可能 |
コンストラクタ注入(推奨) | コンストラクタに @Autowired | 不変性を保てて、テストもしやすい! |
// フィールド注入(非推奨)
@Autowired
private UserRepository repository;
// セッター注入
@Autowired
public void setRepository(UserRepository repository) {
this.repository = repository;
}
// コンストラクタ注入(推奨)
@Autowired
public UserService(UserRepository repository) {
this.repository = repository;
}
Spring Bootでの自動注入(補足)
実はSpring Boot(Spring Framework 4.3以降)では、
コンストラクタが1つしかない場合は @Autowired
を省略してもOKです!
// 省略しても自動注入される
public UserService(UserRepository repository) {
this.repository = repository;
}
依存関係を切り替えてみよう
たとえば、テスト用にダミーのリポジトリを作って注入することもできます。
public class FakeUserRepository extends UserRepository {
@Override
public String findUserName() {
return "テストユーザー";
}
}
これをテストで使えば、実際のDBに依存せずテスト可能です。
「newしない」=DIと思ってもいいのか?
結論からいうと――
「DIとはnewしないこと」=完全ではないけれど、初心者が理解する第一歩としてはOK!
ただし、「newしないこと=依存性を外部から注入すること」という本質を理解することが大事です。
なぜ「newしない」=DIと思ってもいいの?
1. 自分で new
すると、具体的なクラスに依存することになる
// 悪い例(依存が強い)
UserService service = new UserService(new UserRepository());
この書き方では UserService
が UserRepository
の具体的な実装に直接依存しています。
これだと、あとから FakeUserRepository
に差し替えたいときにコードの変更が必要になります。
2. DIの基本は「必要な部品(依存)を外から渡してもらう」こと
// 良い例(依存性注入)
UserRepository repository = new UserRepository(); // または DIコンテナが用意
UserService service = new UserService(repository);
このように、UserService
は UserRepository
を自分ではnewしない。
誰が何を使うかを決める責任を持たない。
これが「疎結合(loose coupling)」という考え方で、保守やテストに強くなる設計になります。
ただし補足があります
「newしないこと=DI」だけで考えると、次のような誤解が生まれる可能性があります:
誤解 | 本当はこう |
---|---|
DIすれば new は一切使わない? | DIコンテナが new してくれているだけです |
newしたらダメ? | 必要なときはOK。依存先を固定しないように |
全部注入しないといけない? | 小さなユーティリティならnewしてもいい場合も |
たとえばSpringでは…
@Service
public class UserService {
private final UserRepository repository;
@Autowired
public UserService(UserRepository repository) {
this.repository = repository;
}
}
ここで UserService
は UserRepository
をnewしていません。
でもSpringのDIコンテナ(ApplicationContext)が裏でnewして注入してくれているのです。
まとめ:DI=「newしないこと」ではなく…
正しくは:
「newする側とされる側を分離し、依存を外部から注入する」こと
→ その結果、「自分でnewしなくてよくなる」という形に見える!
ということですね。
もう一歩深く理解したいですか?
- 「DIの目的=柔軟な設計・保守性・テストのしやすさ」
- 「DIの手段=インターフェースと注入」
こうした観点から見ると、設計の考え方がさらに身につきます!
新人エンジニアが押さえるべきポイント
@Component
や@Service
などで「Springに管理してもらう」宣言をする@Autowired
は「依存を注入してもらう」ための印- コンストラクタ注入がベストプラクティス
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール

- 代表取締役
-
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。
最新の投稿
山崎講師2025年5月19日Javaリフレクションとは?新人エンジニア向けにやさしく解説!
山崎講師2025年5月19日新人エンジニアにやさしく解説!「Unix標準時(UTC)」とは?
山崎講師2025年5月19日ER図設計における「依存」と「非依存」はSQLにどう関係するのか?
山崎講師2025年5月18日SQL初心者がやりがち!知らずに書いてるアンチパターン10選と改善法