こんにちは、かつコーチです。
前回の記事で、SpringはBeanを管理してDIを実現していると説明しました。
Beanを登録するアノテーションには@Componentだけでなく、@Serviceや@Repositoryもあり、初心者の多くが「結局どれを使えばいいの?」と迷います。
この記事では、それぞれの違いと使い分けの判断軸を整理します。
@Component・@Service・@Repositoryとは?
すべて「Beanとして登録する」ためのアノテーション
まず大前提として、@Component・@Service・@Repositoryは、すべて「このクラスをSpringコンテナに登録してBeanにしてください」という意味を持つ点で共通しています。
実は@Serviceと@Repositoryは、内部的に@Componentを含んだ「特殊化されたアノテーション」です。
// Springのソースコード(簡略化したイメージ)
@Component
public @interface Service { ... }
@Component
public @interface Repository { ... }
つまり技術的には、@Serviceや@Repositoryを使うべき場所に@Componentを書いても、動作自体は変わりません。
それでも用途別に使い分けられているのは、コードの「意図」を明確にするためです。
用途別に使い分ける理由
複数人での開発や、久しぶりに自分のコードを見返す場面を想像してください。
クラスに@Serviceと書かれていれば「ここはビジネスロジックの層だ」とひと目で分かりますが、すべて@Componentだと、そのクラスが何を担当しているのか、中身を読まないと判断できません。
アノテーション名を役割に合わせることで、コードそのものが設計図としての役割を果たすようになります。
使い分けの判断軸
@Component:汎用的なBean
@Componentは、他のどの分類にも当てはまらない、汎用的な部品クラスに使います。
例えば、ユーティリティクラスや、複数の層から共通で使われるヘルパークラスなどです。
@Component
public class DateFormatter {
public String formatToJapanese(LocalDate date) {
return date.getYear() + "年" + date.getMonthValue() + "月" + date.getDayOfMonth() + "日";
}
}
@Service:ビジネスロジックを担当する層
@Serviceは、アプリケーションのビジネスロジック(業務上の処理の中身)を担当するクラスに付けます。
「注文を確定する」「割引率を計算する」といった、アプリ固有のルールを実装する層です。
@Service
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void placeOrder(Order order) {
// 在庫チェックや割引計算などのビジネスロジック
orderRepository.save(order);
}
}
@Repository:データベースとのやり取りを担当する層
@Repositoryは、データベースへのアクセス(取得・保存・更新・削除)を担当するクラスに付けます。
@Repository
public class OrderRepositoryImpl implements OrderRepository {
public void save(Order order) {
// データベースへの保存処理
}
}
@Repositoryには、他の2つにはない特別な機能もあります。
データベースアクセス時に発生する例外を、Springが用意した共通の例外クラスに自動変換してくれる機能で、これにより特定のデータベース製品に依存しないエラーハンドリングが書けるようになります。
なお、Spring Data JPAを使う場合はinterfaceを定義するだけでSpringが実装クラスを自動生成してくれるため、@Repositoryを明示的に書く場面は減りますが、考え方自体はこのカテゴリで押さえておく必要があります。
3つの使い分けを一覧で整理する
| アノテーション | 役割 | 主な処理内容 |
|---|---|---|
@Component | 汎用的な部品 | ユーティリティ、共通ヘルパーなど |
@Service | ビジネスロジック層 | 業務ルール、計算、複数Repositoryの組み合わせ |
@Repository | データアクセス層 | データベースへのCRUD操作 |
判断に迷ったときは、「このクラスの主な仕事は何か?」を自問してみてください。
データを保存・取得するだけなら@Repository、業務ルールを処理するなら@Service、それ以外の共通部品なら@Component、という順番で考えると整理しやすくなります。
つまずきやすい設定・注意点
何でも@Serviceに寄せてしまい層が崩れる
初心者にありがちなのが、「とりあえず@Serviceを付けておけば動く」という発想で、本来@Repositoryであるべきデータアクセス処理までServiceクラスの中に書いてしまうパターンです。
❌ Before
@Service
public class OrderService {
// Service層なのに、JDBCの生の接続処理を直接書いてしまっている
public void placeOrder(Order order) {
Connection conn = DriverManager.getConnection(...);
// SQL文を組み立てて実行...
}
}
これでは、テストがしづらくなるだけでなく、後からデータベース製品を変更する際に、ビジネスロジックとデータアクセスの処理が絡み合ってしまい修正範囲が広がります。
✅ After
@Repository
public class OrderRepositoryImpl implements OrderRepository {
public void save(Order order) {
// データアクセスの詳細はここに閉じ込める
}
}
@Service
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void placeOrder(Order order) {
// ビジネスロジックに専念する
orderRepository.save(order);
}
}
筆者自身、学習初期は「動けばいい」でService層に何でも詰め込んでいましたが、後からテストコードを書こうとした際に、データベース接続まで含めてテストしなければならず苦労した経験があります。
役割ごとに層を分けておくことは、後々のテストのしやすさにも直結します。
応用・一歩先の使い方
Spring MVCでは、この3つに加えてリクエストの受け口を担当する@Controller・@RestControllerというアノテーションも登場します。
「Controller(入り口)→ Service(業務ロジック)→ Repository(データアクセス)」という一連の流れを意識しておくと、Spring Bootのレイヤードアーキテクチャの全体像がつかみやすくなります。
Controller層の詳しい違いは、次回の記事で扱います。
まとめ
この記事のポイント
@Component・@Service・@RepositoryはすべてBean登録用のアノテーションで、動作上の違いはほぼない@Componentは汎用部品、@Serviceはビジネスロジック層、@Repositoryはデータアクセス層に使う@Repositoryにはデータベース例外を共通化して変換する機能もある- 役割を意識せず何でも1つの層に詰め込むと、テストや変更がしづらくなる
次に読むべき記事
Service層・Repository層の役割が分かったら、次はリクエストの入り口となる「@Controllerと@RestControllerの違い」を見ていきましょう。
タグ: Spring Boot, 初心者向け, フレームワーク基礎