はじめに
株式会社Good Labでエンジニアをしている コータロー です。
日々、Java・SQL・Gitなどの技術情報や、新人エンジニア向けの学習ノウハウ、
AI活用についての情報を発信しています。
Good Labについて気になった方は、コーポレートサイトもぜひご覧ください。
▶コーポレートサイト
「Java用語、結局なんだっけ?」シリーズの第6回です。
| 回 | テーマ |
|---|---|
| #1 | 環境・基盤編 |
| #2 | DB接続編 |
| #3 | Web/サーバー編 |
| #4 | 環境・DB・Web・例外スレッド |
| #5 | モダンJava編 |
| #6(本記事) | フレームワーク編 |
| #7 | ビルド・運用編 |
今回は フレームワーク編 です。Spring / Spring Boot を中心に、新人〜2年目が「なんとなく使っているけど説明できない」用語を整理します。
この記事のゴール
- Spring と Spring Boot の関係を説明できる
- DI / IoC コンテナ・Bean の役割を理解できる
- AOPが何を解決するか説明できる
- Lombok と JPA の位置づけが分かる
① Spring Framework ― 「Javaの汎用フレームワーク」
一言で言うと
Javaアプリケーション開発を支える、機能の集合体(フレームワーク) です。
2003年から続く老舗で、現代のJavaバックエンドの デファクトスタンダード。
Spring が提供する主な機能
| モジュール | 役割 |
|---|---|
| Spring Core | DI / IoC コンテナ |
| Spring MVC | Webアプリ(Controller、View) |
| Spring Data | DB アクセス(JPA、JDBC等) |
| Spring Security | 認証・認可 |
| Spring AOP | 横断的関心事の処理 |
よくある誤解
- 「Spring = Webフレームワーク」:違う。汎用フレームワーク で、Webは一部の機能。
- 「Spring が重いから Java は遅い」:DIによる起動コストはあるが、実行時パフォーマンスは十分高速。
② Spring Boot ― 「Spring の設定地獄を解消したラッパー」
一言で言うと
Spring を「面倒な設定なしで」すぐ使えるようにしたフレームワーク です。
2014年リリース、現代のSpring案件はほぼ100% Spring Boot。
Spring vs Spring Boot
| 観点 | Spring(昔) | Spring Boot(今) |
|---|---|---|
| XML設定 | 何百行も必要 | ほぼ不要 |
| Tomcat | 別途インストール | 内蔵 |
| 依存解決 | 自分で組む | スターターパック(spring-boot-starter-web等) |
| 起動 | WARをデプロイ |
java -jar app.jar で起動 |
| 設定 | XML |
application.properties または application.yml
|
Spring Boot の3大特徴
- オートコンフィグレーション:クラスパス上の依存を見て、自動で設定を組む
-
スターターパック:
spring-boot-starter-webを入れるだけでWeb開発に必要な依存が揃う - 組み込みサーバー:Tomcat / Jetty / Undertow を内蔵
最小コード例
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@RestController
class HelloController {
@GetMapping("/")
public String hello() {
return "Hello, Spring Boot!";
}
}
これだけで Webサーバーが起動し、http://localhost:8080/ にアクセスすると "Hello, Spring Boot!" が返ります。
よくある誤解
- 「Spring Boot は Spring を置き換えた」:違う。Spring の上に乗っかった設定不要版。中身は同じSpring。
- 「Spring Boot は学習が簡単」:表面はシンプル。だが裏で動いている DI / AOP / Bean を理解するには時間がかかる。
③ DI(依存性注入)/ IoC コンテナ ― 「Springの心臓部」
一言で言うと
| 用語 | 一言で |
|---|---|
| DI(Dependency Injection) | 必要なオブジェクトを「外から渡してもらう」設計 |
| IoC(Inversion of Control) | オブジェクト生成の主導権を「Spring に渡す」設計思想 |
| IoCコンテナ | IoCを実現する仕組み(Spring の中核) |
DI なしの世界
// クラス内で new する(密結合)
public class UserService {
private final UserRepository repository = new UserRepository();
private final EmailNotifier notifier = new EmailNotifier();
// ...
}
問題:
- テスト時に
UserRepositoryをモックに差し替えられない -
UserRepositoryの生成方法が変わったら全部直す必要
DI ありの世界(Spring 流)
@Service
public class UserService {
private final UserRepository repository;
private final EmailNotifier notifier;
// コンストラクタで「外から」受け取る
public UserService(UserRepository repository, EmailNotifier notifier) {
this.repository = repository;
this.notifier = notifier;
}
}
ポイント:
-
UserServiceは 依存オブジェクトを new しない - Spring が必要な依存を 自動で注入 してくれる
- テスト時は モックを渡せる
Spring の DI の仕組み
1. Spring 起動時:@Component / @Service / @Repository のクラスを「Bean」として登録
2. Bean 同士の依存関係を解決
3. 必要な Bean を、必要な場所に注入(コンストラクタ・フィールド・セッター)
よくある誤解
-
「DI =
@Autowiredを付けること」:違う。設計思想全体。@Autowiredは実現手段の1つ。 - 「DI を使うとパフォーマンスが落ちる」:起動時のコストはあるが、実行時はほぼ影響なし。
④ Bean ― 「Springが管理するオブジェクト」
一言で言うと
Spring のIoCコンテナが管理しているJavaオブジェクト のことです。
Bean になる方法
| アノテーション | 用途 |
|---|---|
@Component |
汎用的なBean |
@Service |
サービス層(ビジネスロジック) |
@Repository |
データアクセス層 |
@Controller |
Web の Controller |
@RestController |
REST API の Controller |
@Bean |
@Configuration クラス内で手動定義 |
これらのアノテーションを付けたクラスは、Spring 起動時に インスタンス化されてコンテナに登録 されます。
Bean のスコープ
| スコープ | 説明 |
|---|---|
singleton |
アプリ全体で1つ(デフォルト) |
prototype |
DI されるたびに新規作成 |
request |
HTTPリクエストごとに1つ |
session |
セッションごとに1つ |
新規案件で singleton 以外を使うことは稀です。
よくある誤解
-
「
newで作ったオブジェクトもBean」:違う。Springが管理してこそBean。newで作るとDIが効かない。 -
「Bean は1リクエスト1個」:デフォルトは
singleton(アプリ全体で1個)。
⑤ AOP(アスペクト指向プログラミング) ― 「横断的関心事を分離」
一言で言うと
ログ・トランザクション・認証など「複数のメソッドに共通する処理」を、本処理から切り離して書く仕組み です。
AOP がない世界
public void doSomething() {
log.info("メソッド開始");
long start = System.currentTimeMillis();
// 本処理
repository.save(data);
long elapsed = System.currentTimeMillis() - start;
log.info("メソッド終了: " + elapsed + "ms");
}
「ログ出力」と「本処理」が混在しています。
これがメソッド100個あれば、ログのコードが100箇所に散らばります。
AOP がある世界
// 1. アスペクト(横断処理)を1箇所に定義
@Aspect
@Component
public class LoggingAspect {
@Around("@annotation(Logged)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 本処理を実行
long elapsed = System.currentTimeMillis() - start;
log.info(joinPoint.getSignature() + " : " + elapsed + "ms");
return result;
}
}
// 2. 本処理は素直に書く
@Logged
public void doSomething() {
repository.save(data); // ← ログのコードがなくなった
}
AOP の典型的な用途
| 用途 | Spring の実装 |
|---|---|
| トランザクション | @Transactional |
| キャッシュ | @Cacheable |
| セキュリティ | @PreAuthorize |
| 非同期 | @Async |
| ログ | カスタムアノテーション |
@Transactional が DI とともに AOPの裏で動いている ことを知ると、フレームワークの理解が深まります。
よくある誤解
-
「AOPは特殊な機能」:違う。Spring 案件では
@Transactional等で日常的に使っている。 - 「AOP は性能が落ちる」:実体は プロキシオブジェクト経由の呼び出し。影響は限定的。
⑥ Lombok ― 「ボイラープレートを消すライブラリ」
一言で言うと
getter / setter / コンストラクタ / equals 等を、アノテーション1個で自動生成するライブラリ です。
旧スタイル vs Lombok
// 旧:手書き
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override public boolean equals(Object o) { /* 略 */ }
@Override public int hashCode() { /* 略 */ }
@Override public String toString() { /* 略 */ }
}
// Lombok版
@Data // getter/setter/equals/hashCode/toString を自動生成
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private int age;
}
よく使うアノテーション
| アノテーション | 自動生成するもの |
|---|---|
@Getter / @Setter
|
getter / setter |
@NoArgsConstructor |
引数なしコンストラクタ |
@AllArgsConstructor |
全フィールドのコンストラクタ |
@RequiredArgsConstructor |
final フィールドのコンストラクタ |
@Data |
上記全部入り(@Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor) |
@Slf4j |
log というLoggerを自動定義 |
record と Lombok の使い分け
| 観点 | record | Lombok |
|---|---|---|
| 導入 | Java 16以降の標準機能 | 外部ライブラリ |
| 可変性 | 不変(final固定) | 可変も可能 |
| 継承 | 不可 | 可能 |
| JPAエンティティ | 不向き | OK |
新規コードで 「シンプルな不変データ」なら record、「JPAエンティティや可変オブジェクト」なら Lombok が使い分けの目安です。
よくある誤解
- 「Lombok はJavaの新機能」:違う。外部ライブラリ(アノテーションプロセッサで生成)。
-
「Lombok の
@Dataは便利だから何にでも付ける」:JPAエンティティでは@EqualsAndHashCodeの挙動が問題になることが多い。慎重に。
⑦ JPA / Hibernate ― 「O/Rマッパー」
一言で言うと
| 用語 | 一言で |
|---|---|
| ORM(O/Rマッパー) | オブジェクト(Java)と関係DB(テーブル)の変換ライブラリの総称 |
| JPA(Java Persistence API) | Java の ORM 標準仕様 |
| Hibernate | JPA の代表的な実装 |
JDBC との関係と同じく、JPA は仕様、Hibernate は実装 です。
コード例
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "email")
private String email;
// getter / setter
}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email); // メソッド名から自動でSQL生成
}
// 使う側
User user = userRepository.findById(1L).orElseThrow();
List<User> all = userRepository.findAll();
userRepository.save(new User("田中", "tanaka@example.com"));
JDBC で「INSERT INTO ...」を直接書く代わりに、オブジェクトの保存・取得をメソッド呼び出しでできる のがORMの利点。
JPA のメリット・デメリット
| メリット | デメリット |
|---|---|
| SQLを書かずに済む | 学習コストが高い |
| DBの種類を意識しない | パフォーマンスチューニングが難しい |
| オブジェクトのまま扱える | 思わぬN+1問題が起きやすい |
JPA を使わない選択肢
- MyBatis:SQLを直接書きつつ、結果のマッピングだけORMに任せる
- Spring JDBC:JDBCの薄いラッパー
- jOOQ:型安全なSQL DSL
新人〜2年目のうちは、まずJPAの基本を押さえ、その後MyBatis等にも触れると視野が広がります。
よくある誤解
- 「JPA はDBそのもの」:違う。Java と DB の橋渡し。
- 「JPA を使えば全部速くなる」:N+1問題、遅延ロード等、ORM特有のハマりどころがある。
用語まとめ早見表
| 用語 | 一言で |
|---|---|
| Spring Framework | Javaの汎用フレームワーク |
| Spring Boot | Spring を設定なしで使える形にしたラッパー |
| DI / IoC | 依存を「外から渡す」設計思想 |
| IoCコンテナ | DI を実現する仕組み(Springの中核) |
| Bean | IoCコンテナが管理するオブジェクト |
| AOP | 横断的関心事(ログ・トランザクション等)を分離 |
| Lombok | ボイラープレートを自動生成する外部ライブラリ |
| JPA | Java の ORM 標準仕様 |
| Hibernate | JPA の代表的な実装 |
現場あるある誤解集
| ❌ 誤解 | ⭕ 正しい理解 |
|---|---|
| 「Spring Boot は Spring の置き換え」 | Spring の上に乗っかった設定不要版 |
「@Autowired がDI」 |
DI は思想全体。@Autowired は実現手段 |
| 「new で作ったオブジェクトもBean」 | Springが管理してこそBean |
「@Transactional は普通のメソッドの機能」 |
中身はAOPで動いている |
| 「Lombok = Javaの新機能」 | 外部ライブラリ(アノテーションプロセッサ) |
| 「JPA = Hibernate」 | JPAは仕様、Hibernateは実装 |
| 「Bean のスコープは1リクエスト1個」 | デフォルトは singleton(アプリ全体で1個) |
演習問題
問題1:Spring と Spring Boot ⭐
次のうち、Spring Boot 固有の機能 はどれですか?
- A. DI / IoCコンテナ
- B. AOP
- C. オートコンフィグレーション
- D.
@Service、@Repositoryアノテーション
模範解答
正解:C
解説:
- C のオートコンフィグレーション は Spring Boot 固有
- A、B、D は Spring Framework の機能(Spring Boot でも使えるが、Spring 由来)
ポイント:Spring Boot は Spring の上に「設定を自動化する仕組み」を載せたもの。基本機能はすべて Spring 由来。
問題2:DI / Bean ⭐
次のクラスは Spring の Bean として登録されますか?
public class CalculatorService {
public int add(int a, int b) {
return a + b;
}
}
模範解答
正解:登録されない
解説:
- Spring の Bean になるには、
@Component、@Service、@Repository、@Controllerなどのアノテーションが必要 - またはJava Config(
@Beanメソッド)で明示的に登録する必要がある - このクラスは何のアノテーションもないので Bean にはならず、DIされない
修正例:
@Service
public class CalculatorService {
public int add(int a, int b) {
return a + b;
}
}
ポイント:Spring は「アノテーションが付いたクラス」を Bean として登録する。new してもDIは効かない。
問題3:JPA と Hibernate ⭐
次のうち、正しい説明 はどれですか?
- A. JPA は MySQL 専用の機能
- B. Hibernate がデフォルトの JPA 実装
- C. JPA を使うと SQL を全く書かなくなる
- D. JPA は Spring Boot にしか組み込めない
模範解答
正解:B
解説:
-
B が正解:Spring Boot の
spring-boot-starter-data-jpaを入れると、デフォルトで Hibernate が使われる - A は誤り:JPA は DB 非依存の仕様。MySQL も PostgreSQL も Oracle も使える
- C は誤り:複雑なクエリでは
@Queryで JPQL や SQL を直接書く こともある - D は誤り:JPA は Spring Boot に依存しない。Jakarta EE のサーバー(GlassFish等)でも使える
ポイント:JPA と Hibernate の関係は、JDBC と MySQL Connector/J の関係と同じ(仕様 vs 実装)。
まとめ
フレームワーク編の9用語のおさらいです。
- Spring Framework:Javaの汎用フレームワーク
- Spring Boot:Spring を設定なしで使える形にしたラッパー
- DI / IoC:依存を外から渡す設計思想
- IoCコンテナ:DI を実現する仕組み
- Bean:IoCコンテナが管理するオブジェクト
- AOP:横断的関心事を分離する仕組み
- Lombok:ボイラープレートを自動生成するライブラリ
- JPA:Java の ORM 標準仕様
- Hibernate:JPA の代表的な実装
新人〜2年目のうちに「仕様と実装の分離」「依存を外から渡す」という設計思想を掴んでおくと、Spring 案件で「なんでこう書くんだろう?」と迷う場面が激減します。
次回予告
次回(#7・最終回)は ビルド・運用編 です。
- Maven / Gradle / プラグイン / 依存性
- JUnit / Mockito
- JAR / WAR / EAR の使い分け
を解説します。
参考
@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!