📝 はじめに
先日、後輩からフレームワークって意味あんの?(意訳)という質問を受けました。
Java初学者にとって、Spring Bootの便利さはなかなか実感しづらいものです。
「アノテーションが多すぎて魔法みたい」「結局中で何が起きているの?」と思う人も多いのではないでしょうか?
この記事では、同じ機能をSpring Bootと純Javaの2通りで実装してみて、フレームワークの偉大さを体感します。
🎯 目標
/user?id=1
にアクセスしたとき、
Hello, Alice!
のようにユーザー名を返すAPIを作ります。
🤖 1. Spring Bootで実装(DI + MVC)
🧩 事前準備
いきなり初心者のつまづきポイントですが、
Spring Bootを利用したプロジェクトは、単体では実行できません。
そのためgradleやmaven等のビルドツールのインポート・環境設定が必要となります。
各々解りやすい記事があったのでご参照ください。
📁 ディレクトリ構成
src/main/java/
├── Application.java # アプリの起点
├── controller/UserController.java
├── model/User.java
└── service/UserService.java
🔸 Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
🔸 User.java
(Model)
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
}
🔸 UserService.java
(Service)
@Service
public class UserService {
private final Map<Integer, User> userMap = new HashMap<>();
public UserService() {
userMap.put(1, new User(1, "Alice"));
userMap.put(2, new User(2, "Bob"));
userMap.put(3, new User(3, "Chris"));
}
public User getUserById(int id) {
return userMap.getOrDefault(id, new User(id, "Unknown"));
}
}
🔸 UserController.java
(Controller)
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public String getUserName(@RequestParam int id) {
User user = userService.getUserById(id);
return "Hello, " + user.getName() + "!";
}
}
▶️ 実行と動作確認(Gradleの場合)
$ gradle build
$ gradle run
http://localhost:8080/user?id=1 → Hello, Alice!
⚙️ 2. フレームワークなし(純Java)
📁 ディレクトリ構成
java/
├── Main.java
├── User.java
├── UserService.java
└── UserHandler.java
🔸 User.java
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
}
🔸 UserService.java
public class UserService {
private final Map<Integer, User> userMap = new HashMap<>();
public UserService() {
userMap.put(1, new User(1, "Alice"));
userMap.put(2, new User(2, "Bob"));
}
public User getUserById(int id) {
return userMap.getOrDefault(id, new User(id, "Unknown"));
}
}
🔸 UserHandler.java
public class UserHandler implements HttpHandler {
private final UserService userService;
public UserHandler(UserService userService) {
this.userService = userService;
}
@Override
public void handle(HttpExchange exchange) {
try {
String query = exchange.getRequestURI().getQuery();
int id = Integer.parseInt(query.split("=")[1]);
User user = userService.getUserById(id);
String response = "Hello, " + user.getName() + "!";
exchange.sendResponseHeaders(200, response.length());
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
🔸 Main.java
public class Main {
public static void main(String[] args) throws Exception {
UserService userService = new UserService();
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/user", new UserHandler(userService));
server.setExecutor(null);
server.start();
System.out.println("Server started on port 8080");
}
}
▶️ 実行と動作確認
$ javac *.java
$ java Main
http://localhost:8080/user?id=1 → Hello, Alice!
📊 比較まとめ
項目 | Spring Boot | 純Java |
---|---|---|
ルーティング | @GetMapping("/user") |
HttpServer.createContext(...) |
サーバ起動 | 組み込みTomcat | Java SEのHttpServer
|
MVC構造 | 明確(Controller/Service/Model) | プログラマの設計に委ねられる |
DI(依存性注入) |
@Service + 自動コンストラクタDI |
手動でnew して渡す |
保守性・拡張性 | 高(テスト・分割・拡張が楽) | 低〜中(コードが肥大化しやすい) |
💡 学びのポイント
- Spring Bootは手間のかかる処理を裏で肩代わりしてくれる
- Springによりコード量が削減できるので、テストも楽になる
- Springのプロジェクトを動作させるには多少の事前準備が必要となる
- 個人開発・小規模では純Javaもアリだが、大規模なプロジェクトではSpringの恩恵が大きい
💐 おわりに
私が初めてJavaを学習したときはアノテーションについて何の疑問も抱かず使っていました。
学んだことをすぐに解釈して疑問点を明確にできる、後輩くんはエンジニア気質◎ですね✨
「Springはよくわからない魔法」から抜け出す第一歩になることを願っています!
また、私自身まだまだ3年目のヒヨッ子🐣ですので、記事に不足あればご指摘お願いします。