Claude Code に古い Spring Boot コードを書かせない:CLAUDE.mdで制御する実践ガイド

はじめに

Spring Boot 3.xへの移行後、Claude Codeに書かせたコードがビルドエラーになるケースが増えている。javax.persistence.*のインポートやWebSecurityConfigurerAdapterの継承はSpring Boot 3.xではコンパイルすら通らない。CLAUDE.mdとPostToolUseフックを組み合わせれば、古いコードの混入を防げる。


Claude Codeが生成しやすい古いSpring Bootパターンを正す

`javax.*`から`jakarta.*`への名前空間移行

Spring Boot 3.0からJakarta EE 9ベースになり、JPA・バリデーション・サーブレット系パッケージがjakarta.*に変わった。


// ❌ Spring Boot 2.x
import javax.persistence.Entity;
import javax.validation.constraints.NotBlank;
import javax.servlet.http.HttpServletRequest;
// ✅ Spring Boot 3.x
import jakarta.persistence.Entity;
import jakarta.validation.constraints.NotBlank;
import jakarta.servlet.http.HttpServletRequest;

javax.sql.*javax.crypto.*はJava SEのパッケージのため変更不要だ。全て置き換えると逆にエラーになる。

`WebSecurityConfigurerAdapter`の廃止

Spring Security 6(Spring Boot 3同梱)ではWebSecurityConfigurerAdapterが完全削除された。


// ❌ Spring Boot 2.x(Spring Boot 3でコンパイルエラー)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/public/**").permitAll()
            .anyRequest().authenticated().and().formLogin().and().csrf().disable();
    }
}

// ✅ Spring Boot 3.x
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .authorizeHttpRequests(a -> a.requestMatchers("/public/**").permitAll().anyRequest().authenticated())
            .formLogin(f -> f.loginPage("/login").permitAll())
            .csrf(c -> c.disable()).build();
    }
}

`@Autowired`フィールドインジェクション→コンストラクターインジェクション


// ❌ フィールドインジェクション
@Service
public class OrderService {
    @Autowired private OrderRepository repo;
    @Autowired private PaymentGateway gateway;
}
// ✅ コンストラクターインジェクション(Lombok)
@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderRepository repo;
    private final PaymentGateway gateway;
}

@RequiredArgsConstructorfinalフィールドのコンストラクターが自動生成される。


CLAUDE.mdで制御する完全テンプレート


# Spring Boot 3.x ルール

- インポート: jakarta.* を使う(javax.persistence.* / javax.validation.* / javax.servlet.*)
  例外: javax.sql.* / javax.crypto.* はJava SEのため変更なし
- DI: @Autowired フィールドDI禁止 → コンストラクター + @RequiredArgsConstructor
- Security: WebSecurityConfigurerAdapter 禁止(削除済み)→ SecurityFilterChain @Bean
  ラムダDSL必須。.and() / antMatchers() / authorizeRequests() 禁止
- HTTP: new RestTemplate() 禁止 → RestClient(同期)/ WebClient(非同期)
- JPA: JpaRepository<T, ID> を使う
- テスト: @MockBean 禁止(3.4以降非推奨)→ @MockitoBean
- Maven: ./mvnw が存在する場合はmvnwを使う

PostToolUseフックで非推奨パターンを自動検出する

Javaファイル編集後に非推奨パターンを検出するフックを設定する。


#!/bin/bash
# scripts/check-deprecated.sh
C=$(jq -r '.tool_input.content // empty')
echo "$C" | grep -qE "import javax\.(persistence|validation|servlet)" \
  && echo "ERROR: javax.* → jakarta.* を使ってください" && exit 1
echo "$C" | grep -q "WebSecurityConfigurerAdapter" \
  && echo "ERROR: WebSecurityConfigurerAdapter削除済み → SecurityFilterChain" && exit 1
echo "$C" | grep -q "boot\.test\.mock.*MockBean" \
  && echo "ERROR: @MockBean非推奨 → @MockitoBean" && exit 1
exit 0

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{ "type": "command", "command": "bash scripts/check-deprecated.sh" }]
    }]
  }
}

EM視点──チームのSpring Boot標準をAIに守らせる

Spring Boot 3.x移行期にClaude Codeが古いパターンを生成するリスクは大きい。CLAUDE.mdをリポジトリにコミットすれば、個人の熟練度に関係なく全員のClaude Codeが同じルールで動く。CIにOpenRewriteのUpgradeSpringBoot_3_3レシピを組み込むと、AI生成コードも含めてjavax.*を機械的に検出できる。PostToolUseフックとCIの二重チェックでコードレビューの指摘を大幅に減らせる。


まとめ

Claude CodeがSpring Bootで生成しやすい古いパターンはjavax.*インポート・WebSecurityConfigurerAdapter@Autowiredフィールドインジェクションだ。本記事のCLAUDE.mdテンプレートを今すぐプロジェクトにコミットしてほしい。PostToolUseフックを合わせて設定すれば、古いコードが混入した瞬間にClaude Codeが自己修正する。

コメント

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