🧑‍💻 Spring Framework 講座【第9回】役割分担の明確化!〜アノテーションベースの設定 (2) – @Component系〜

docs

前回は、DIを実現する @Autowired と、注入候補が複数ある場合に使う @Qualifier について学びました。

今回は、いよいよSpringのBeanを定義するための基本的なアノテーション @Component と、それから派生した @Service@Repository@Controller の役割について詳しく解説します。これらのアノテーションは、業務システムの**「三層構造」**に対応しており、コードの役割分担を明確にするために不可欠です。

1. 業務システムの「三層構造」とは?

業務システムは、一般的に以下の3つの層に分けて設計されます。この構造を採用することで、コードの変更が他の層に波及するのを防ぎ、システム全体の保守性と柔軟性が向上します。

層の名称役割主なタスク
プレゼンテーション層 (Controller)ユーザーとの接点。リクエストの受付と結果の返却。HTTPリクエストの受付、パラメータの解析、画面表示。
ビジネスロジック層 (Service)業務ルールや処理手順を記述する中心部分。データの加工、複雑な計算、トランザクション管理。
データアクセス層 (Repository)データベースとのデータのやり取りを担当。SQL実行、データの永続化(保存)、検索。

Springの @Component 系アノテーションは、これらの層を表現するために用意されています。


2. 基本となるアノテーション:@Component

@Component は、Beanを定義するための最も基本的なアノテーションです。

Springコンテナは、クラスパス(プロジェクトのフォルダ)をスキャン(走査)し、@Component が付いているクラスを見つけると、それをBeanとしてコンテナに登録します。

Java

// Springコンテナに汎用的な部品として登録される
@Component
public class UtilityComponent {
    public String formatData(String rawData) {
        // ... データ整形処理
        return rawData.toUpperCase();
    }
}

実は、これから説明する @Service@Repository@Controller の全てが、内部的にはこの @Component を含んでいます(ステレオタイプアノテーションと呼ばれます)。つまり、@ServiceComponent に置き換えても、Springの動作自体は変わりません。

しかし、役割を明確にするため、通常は用途に応じた専用のアノテーションを使います。


3. 各層に対応する専用アノテーション

3-1. @Controller(プレゼンテーション層)

@Controller は、主にWebアプリケーションのリクエスト受付応答を担当するクラスに付けます。

  • 役割: 外部からのHTTPリクエストを受け取り、どの業務ロジック(Service)を呼び出すかを制御します。
  • 特徴: Spring Web MVCと連携するための特別な機能(例えば、ビューの解決やリクエストマッピングなど)を持っています。

Java

@Controller // または @RestController(API開発用)
public class ItemController {
    
    @Autowired
    private ItemService itemService; // Service層に処理を委譲

    // ... リクエストマッピングの記述
}

3-2. @Service(ビジネスロジック層)

@Service は、業務ロジックを実行するクラスに付けます。

  • 役割: 複数のRepositoryを組み合わせて業務処理を完成させたり、複雑な計算やデータの加工を行ったりします。
  • 特徴: ビジネス処理の中心であるため、後述するトランザクション管理の機能が付加されることがあります(第27回で詳述)。

Java

@Service
public class OrderService {
    
    @Autowired
    private ItemRepository itemRepository; // Repository層にデータアクセスを委譲
    
    // 複数の処理を組み合わせた業務ロジック
    public void createNewOrder(String itemName) {
        if (itemRepository.checkStock(itemName) > 0) {
            // ... 注文作成、在庫引き落としなどの複雑な処理
        }
    }
}

3-3. @Repository(データアクセス層)

@Repository は、データベースなどの永続化層へのアクセスを担当するクラスに付けます。

  • 役割: データベースへのデータの保存(INSERT)、更新(UPDATE)、検索(SELECT)といったデータアクセス処理に特化します。
  • 特徴: データベース固有の例外(エラー)をSpringが用意した共通の例外に自動で変換する機能が付加されます。

Java

@Repository
public class UserRepository {
    
    // データベース接続オブジェクトなどを使ってデータを操作
    public void saveUser(User user) {
        // ... データベースへの保存処理
    }
    
    public User findById(int id) {
        // ... データベースからの検索処理
        return null;
    }
}

4. 適切なアノテーションを使う重要性

「全て @Component にしても動くのなら、全部それでいいのでは?」と思うかもしれません。

しかし、専用のアノテーションを使うことには、以下の大きなメリットがあります。

  1. 可読性の向上: @Service と書かれていれば、「このクラスは業務ロジックを実行する部分だ」と役割が一目でわかります。
  2. 機能の付与: @Service@Repository には、Springが特別な機能(トランザクション管理や例外変換)を付与する可能性があります。将来的にその機能を使いたくなったとき、アノテーションを付け替える必要がなくなります。

✅ 本日のまとめ

  • SpringのBeanは、主に @Component 系のアノテーションを使って定義する。
  • @Component は汎用的な基盤アノテーションであり、他の3つも内部的にはこれを含んでいる。
  • @Controllerプレゼンテーション層(リクエスト受付)を担当。
  • @Serviceビジネスロジック層(業務処理)を担当。
  • @Repositoryデータアクセス層(データベース接続)を担当。
  • これらを使い分けることで、システムの役割分担が明確になり、保守性が向上する。

🔔 次回予告

これで、Beanの定義とDIの仕組みが明確になりました。Springコンテナは、Beanを生成し、DIによってそれらを結びつけていますが、Beanは一度作られたら終わりではありません。

次回は、Beanの「スコープ」と「ライフサイクル」について学びます。特に、Beanが**「アプリケーション全体で一つだけなのか(Singleton)」、それとも「使うたびに新しく生成されるのか(Prototype)」**を制御する方法について深く理解しましょう。

次回:【第10回】Beanのスコープとライフサイクル にご期待ください!

コメント

タイトルとURLをコピーしました