0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Spring Bootで覚えたい便利なアノテーション10選

0
Posted at

はじめに

Spring Bootでの開発を始めると、アノテーションが大量に登場して最初は戸惑いがちです。
この記事では、API開発で特によく使うアノテーション10個を厳選して紹介します。
コード例と「うれしい点」もセットで解説するので、実務でもすぐ使えるはずです。

対象読者:Spring Bootを使い始めた方、アノテーションの意味を改めて整理したい方

まず覚えるならこの6つ

アノテーション 一言メモ
@RestController REST API用Controllerの定番
@GetMapping / @PostMapping URLとHTTPメソッドの紐づけ
@RequestBody JSONをJavaオブジェクトに自動変換
@PathVariable URLの一部を引数として受け取る
@Valid 入力バリデーションを自動化
@Transactional トランザクション管理を自動化

これだけでも、Spring BootのAPI開発がかなりやりやすくなります。

1. @RestController

何が便利?

REST API用Controllerを書くときの定番です。
@Controller + @ResponseBody をまとめたものなので、JSONを返すAPIで超便利です。

@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping("/{id}")
    public UserResponse getUser(@PathVariable Long id) {
        return new UserResponse(id, "Taro");
    }
}

うれしい点

  • 毎回 @ResponseBody を書かなくていい
  • API開発がかなりスッキリする

2. @RequestMapping / @GetMapping / @PostMapping

何が便利?

URLとHTTPメソッドを簡単に紐づけできます。

@GetMapping("/list")
public List<UserResponse> list() {
    return service.findAll();
}

@PostMapping("/create")
public void create(@RequestBody UserRequest request) {
    service.create(request);
}

うれしい点

  • APIの入口が一目でわかる
  • GETPOSTPUTDELETE を明確に書ける

@RequestMapping(method = RequestMethod.GET) と書くより @GetMapping のほうがシンプルです。
最近は @GetMapping / @PostMapping / @PutMapping / @DeleteMapping を使うのが主流です。

3. @RequestBody

何が便利?

JSONリクエストをJavaオブジェクトに自動変換してくれます。
POST以外のPUT・PATCHでも使えます。

@PutMapping("/{id}")
public void update(@PathVariable Long id, @RequestBody UserRequest request) {
    service.update(id, request);
}

うれしい点

  • JSONパースを自分で書かなくていい
  • API入力の受け取りがめちゃくちゃ楽

4. @PathVariable

何が便利?

URLの一部をそのまま引数として受け取れます。

@GetMapping("/{id}")
public UserResponse find(@PathVariable Long id) {
    return service.findById(id);
}

例: /users/10id = 10

うれしい点

  • RESTっぽいURL設計と相性が良い
  • パラメータの取り回しが自然

5. @RequestParam

何が便利?

クエリパラメータを簡単に受け取れます。

@GetMapping("/search")
public List<UserResponse> search(@RequestParam String name) {
    return service.searchByName(name);
}

例: /users/search?name=Taro

defaultValue を使うとページングにも対応できます。

@GetMapping("/list")
public List<UserResponse> list(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "20") int size
) {
    return service.findAll(page, size);
}

うれしい点

  • 検索条件やフラグ受け取りに最適
  • requireddefaultValue も設定できる

6. @Valid

何が便利?

入力チェックを自動で走らせられます。
APIのバリデーションでかなり強力です。

@PostMapping("/create")
public void create(@Valid @RequestBody UserRequest request) {
    service.create(request);
}
public class UserRequest {
    @NotBlank
    private String name;

    @Min(0) @Max(150)
    private int age;

    @Email
    private String email;
}

うれしい点

  • nullチェックや桁チェックを手書きしなくていい
  • 入力不正を早い段階で止められる

@Valid 単体ではエラーレスポンスが500になることがあります。
@RestControllerAdvice と組み合わせて、400系のエラーレスポンスを返す設計にするのがオススメです。

7. @Service

何が便利?

「これは業務ロジックのクラスです」と明示できます。

@Service
public class UserService {
    public UserResponse findById(Long id) {
        return new UserResponse(id, "Taro");
    }
}

うれしい点

  • クラスの役割がわかりやすい
  • SpringのDIコンテナに自動登録される

8. @Repository

何が便利?

DBアクセス用クラスに付ける定番です。

@Repository
public class UserRepository {
    public User findById(Long id) {
        // DBアクセス
        return new User();
    }
}

うれしい点

  • 永続化層だと明確に伝わる
  • DB例外を DataAccessException にラップして変換してくれる(JPA使用時など)

JPA + Spring Data JPAを使う場合、JpaRepository を継承するだけで @Repository を省略できます。

9. @Transactional

何が便利?

トランザクション管理を自動化できます。
DB更新が複数ある処理ではほぼ必須級です。

@Transactional
public void register(UserRequest request) {
    userRepository.insert(...);
    historyRepository.insert(...);
}

参照系処理には readOnly = true を付けると、Hibernateの最適化が効いてパフォーマンスが向上します。

@Transactional(readOnly = true)
public UserResponse findById(Long id) {
    return userRepository.findById(id);
}

うれしい点

  • 途中で失敗したらまとめてロールバックできる
  • 整合性を守りやすい

注意点

  • private メソッドに付けても効きません(Springのプロキシ機能の制約)
  • 同一クラス内からの内部呼び出しでも効かないケースがあります
  • 更新系は readOnly = false(デフォルト)、参照系は readOnly = true で使い分けましょう

10. @Autowired とコンストラクタインジェクション

何が便利?

依存オブジェクトを自動注入してくれます。

// フィールドインジェクション(昔の書き方)
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
}

ただし、現在はコンストラクタインジェクションが推奨です。

// コンストラクタインジェクション(推奨)
@Service
public class UserService {
    private final UserRepository userRepository;

    // コンストラクタが1つだけなら @Autowired は省略可能(Spring 4.3以降)
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

うれしい点

  • new しなくていい
  • テストしやすい構成にしやすい

コンストラクタインジェクションが推奨される理由

観点 コンストラクタDI フィールドDI
final で不変にできる
テストで new して使える
循環依存をコンパイル時に検出

Lombokの @RequiredArgsConstructor を使うと、コンストラクタの定義も省略できてさらにスッキリします。

おまけ:実務でよく見るアノテーション

10個に絞りましたが、実務ではこのあたりもかなり使います。

アノテーション 一言メモ
@SpringBootApplication エントリーポイントの定番。@Configuration + @EnableAutoConfiguration + @ComponentScan の合体版
@Component @Service / @Repository に分類しにくいBeanに使う汎用アノテーション
@Configuration / @Bean JavaコードでBeanを定義するときに使う
@Value application.properties の値をフィールドに注入できる
@RestControllerAdvice API全体の例外ハンドリングを一か所にまとめられる。実務では必須に近い
@ExceptionHandler @RestControllerAdvice と組み合わせて使うことが多い
@Scheduled 定期バッチ処理に便利。cron式も書ける
@Slf4j(Lombok) ロガーの定義を1行に省略できる
@Data(Lombok) getter / setter / equals / hashCode などを自動生成
@Builder(Lombok) Builderパターンのコードを自動生成

まとめ

# アノテーション 役割
1 @RestController REST API用Controller
2 @GetMapping / @PostMapping URLとHTTPメソッドの紐づけ
3 @RequestBody JSONをJavaオブジェクトに変換
4 @PathVariable URLパスを引数に受け取る
5 @RequestParam クエリパラメータを受け取る
6 @Valid 入力バリデーションの自動化
7 @Service 業務ロジック層のBean登録
8 @Repository 永続化層のBean登録
9 @Transactional トランザクション管理の自動化
10 コンストラクタDI 依存オブジェクトの自動注入

これをベースに、@RestControllerAdvice による例外ハンドリングや @Scheduled を使ったバッチ処理なども組み合わせていくと、実務レベルのSpring Boot開発がどんどん書けるようになります。

ぜひ手を動かして試してみてください!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?