Spring Bootで誰もが一度はつまずきやすいポイントを、Javaの経験が浅い方でも無理なく理解できるように、できるだけ難しい言葉を使わずに解説していくシリーズです。今回は第1章「プログラム構成編」として、Spring Bootが目指す「4つの層」という考え方を、図を使いながらひとつずつ理解していきましょう。
まずは全体像から

まずは、Spring Bootが採用するSpringフレームワークが、どんな形でプログラムを組み立てるのか、その全体像から見ていきます。
Springでは、プログラムを大きく「4つの層」に分けて組み立てていきます。役割の異なる4つのまとまりに分けて整理していく、というイメージです。この考え方は、一般的には「MVC」や「レイヤードアーキテクチャ」などと呼ばれます。
ただ、こうした専門用語は、今の段階では無理に覚えなくて大丈夫です。ここではまず、「Springは役割ごとに4つの層に分けてプログラムを作るんだ」という大きな方針だけつかんでいただければ十分です。
それでは、その4つの層が具体的にどんなものなのか、1つずつ見ていきましょう。
SpringBootの4層構成

こちらが、Spring Bootのプログラム構成の全体像です。プログラムが4つの層に分かれていることが分かります。上から順に、プレゼンテーション層、アプリケーション層、ドメイン層、インフラ層です。
各層の役割を整理すると、次のようになります。
| 層 | 役割 |
|---|---|
| プレゼンテーション層 | 画面表示やUIなど、ユーザーと直接やり取りする部分 |
| アプリケーション層 | 外から来た要求を受け取り、必要な処理を呼び出す入り口 |
| ドメイン層 | 業務ロジック(アプリケーションの中心となる処理) |
| インフラ層 | データベースやファイルとの入出力 |
ここで注目してほしいのは、層と層をつなぐ矢印です。矢印は、上から下への一方向になっています。つまりSpring Bootでは、上の層が下の層を呼び出す、という流れでプログラムを整理します。
なぜ層に分けるのか?
理由は大きく3つあります。
- 役割ごとに分担できる ― どの処理をどこに書くのか、置き場所が明確になります。
- 指揮系統がはっきりする ― 上の層が下の層を呼ぶ形にすることで、処理の流れを追いやすくなります。
- 読みやすく、変更に強くなる ― 役割が分かれているため、あとから修正するときも影響範囲を考えやすくなります。
次に、この4つの層がSpring Bootのコード上でどう表現されるのか、アノテーションとあわせて見ていきましょう。
各層と対応アノテーション

続いて、先ほどの4つの層が、コード上ではどのように表現されるのかを、もう少し実装レベルに落とし込んで見ていきます。
Springでは、それぞれの層を担当するクラスに、「アノテーション」と呼ばれる目印を付けます。これによって、「このクラスはどの層の部品なのか」を、フレームワークに伝えることができます。
| 層 / 部品 | アノテーション | 役割 |
|---|---|---|
| アプリ層 / コントローラ | @Controller / @RestController | リクエストを受け取り、ドメイン層の処理を呼び出す |
| ドメイン層 / サービス | @Service | 業務ロジック(アプリの本体となる処理)を書く |
| インフラ層 / リポジトリ | @Repository | データベースやファイルへの読み書き |
| 全体設定 | @Component / @Configuration | 層に限らず、共通的な部品や設定クラスに付ける |
コントローラ(アプリ層)
コントローラには、@Controller、または @RestController を付けます。画面を表示する場合は @Controller、データをそのままやり取りする場合は @RestController を使うことが多いです。
@Controller
public class ControllerClass {
:
}
サービス(ドメイン層)
サービスには、@Service を付けます。ここには、業務ロジック、つまりアプリの本体となる処理を書いていきます。
@Service
public class ServiceClass {
:
}
リポジトリ(インフラ層)
リポジトリには、@Repository を付けます。データベースやファイルへの読み書きを担当します。
@Repository
public class RepositoryClass {
:
}
共通部品・設定クラス
@Component や @Configuration は、特定の層に限らず、アプリ全体で使う共通的な部品や、設定クラスに付けるアノテーションです。
@Component
public class ComponentClass {
:
}
このように、アノテーションを付けるだけで、それぞれのクラスがSpringに「部品」として認識され、管理されるようになります。
ところで、こうして登録されたコントローラ、サービス、リポジトリは、お互いを呼び出して連携します。しかし、コードのどこを見ても、これらを自分で new して組み立てている箇所はありません。では、誰がこれらの部品をつなぎ合わせているのでしょうか。
それを実現しているのが、DI(ディペンデンシー・インジェクション)です。日本語では「依存性の注入」と呼ばれる仕組みです。DIについては、次の章「DI編」でじっくり解説します。ここでは、「アノテーションで登録した部品を、Springが自動でつないでくれる」とイメージしておいてください。
それでは、部品の対応関係が分かったところで、次は実際の処理の流れをシーケンス図で追いかけてみましょう。
処理の流れ(シーケンス)

ここまでに整理した部品を使って、ひとつの処理が始まってから終わるまでの流れを、シーケンス図で時間を追って見ていきましょう。
図の見方は次のとおりです。
- 時間は上から下へと流れます
- 上に並んでいるのが登場人物で、左から「画面」「コントローラ」「サービス」「リポジトリ」、右側が記録媒体の「データベースやファイル」です
- 各登場人物の下に伸びる縦の点線がライフライン、その上に重なる細い長方形は、その部品が処理を行っている時間を表します
それでは、図の番号の順に追っていきます。
行き ― リクエストが奥へ伝わる
- リクエスト ― 画面でボタンが押され、コントローラにリクエストが送られます。これが処理の出発点です。
- ドメイン呼び出し ― コントローラがドメイン層のサービスを呼び出します。コントローラ自身は業務ロジックを持たず、あくまで処理の「呼び出し役」だという点がポイントです。
- データ取得・登録 ― 呼び出されたサービスは、データの取得や登録が必要になると、インフラ層のリポジトリにその処理を依頼します。
- 参照・更新 ― リポジトリは、記録媒体であるデータベースやファイルに対して、実際の参照や更新を行います。
帰り ― 結果が画面へ戻る
- 結果 ― リポジトリが記録媒体から結果を受け取ります。記録媒体へのアクセスは、必ずこのリポジトリを介して行われる、という点を押さえてください。
- 結果を返す ― リポジトリからサービスへ結果を返します。
- 処理結果 ― サービスからコントローラへ処理結果を返します。
- 画面へ返す ― 最後にコントローラから画面へと結果を返し、画面に結果が表示されます。
このように、それぞれの層が自分の役割だけに専念し、決められた順番で「呼び出し」と「返却」を繰り返していくのが、Springフレームワークが目指す処理の流れです。
まとめ

それでは、この「プログラム構成編」の内容をまとめます。ポイントは大きく2つです。
- 4層 = プレゼン → アプリ → ドメイン → インフラ ― Springのプログラムは4つの層で構成され、プレゼンテーション層からインフラ層へと、決められた順番で呼び出されていきます。
- 各層に対応するアノテーションを付ける ― それぞれの層を担当するクラスに、
@Controller、@Service、@Repositoryといった対応するアノテーションを付け、Springに「どの層の部品か」を認識させます。
この「層ごとに役割を分ける」こと。そして「アノテーションで部品として登録する」こと。この2つの考え方が、Springアプリケーションの土台になります。
そして、アノテーションで登録した部品同士を、どうやってつなぎ合わせるのか。その答えが、次の章でお話しするDI(依存性の注入)です。



