【Spring Boot】 アノテーションまとめ

## 始めに
こんにちは。
今回はSpring Bootを学習する中で出会ったたくさんのアノテーションについて、自分なりにまとめてみました。

## アノテーションとは？
アノテーションとは、訳すと「注釈・注記」といった意味を持つ言葉で、
実行環境や外部ソフトウェアに対して、プログラムがどういうものか・何をやってほしいのかを伝えるためのもの。

## Spring Bootで使われるアノテーション
### 【DIに関するアノテーション】
#### @&#xFFF0;Autowired
クラスのフィールドに付与することで、使いたいクラスをインスタンス化し、変数に設定してくれるアノテーション。

#### @&#xFFF0;Component
インスタンス化させたいクラスに付与するアノテーション。
このアノテーションを付与することでDIコンテナにBeanとして登録され、@&#xFFF0;Autowiredが付与されたフィールドにインスタンスが注入される。

#### @&#xFFF0;Controller 
インスタンス化させたいクラスに付与するアノテーションその２。
クライアントとのデータ入出力を制御する（画面からHTTPリクエストを受け付ける）クラスに付与する。

#### @&#xFFF0;Service
インスタンス化させたいクラスに付与するアノテーションその３。
業務ロジックを提供するクラスに付与する。

#### @&#xFFF0;Repository
インスタンス化させたいクラスに付与するアノテーションその４。
データベースとのやりとりを行うクラスに付与する。

#### @&#xFFF0;Configuration
アノテーションを使ってのDIコンテナへのBean登録が複雑な場合、JavaConfigと呼ばれるBeanを生成するクラスを作成する。そのJavaConfigに付与するアノテーション。

#### @&#xFFF0;Bean
@&#xFFF0;Configurationが付与されたJavaConfig内のインスタンスを生成するメソッドに付与するアノテーション。

```java:実装例
@Configuration
public class TeatConfig {

  // TestComponentクラスをDIコンテナに登録する
  @Bean 
  public TestComponent testComponent() {
    return new TestComponent();
  }
}
```

#### @&#xFFF0;Scope
インスタンスの生成・破棄のタイミングを指定するアノテーション。

```java:実装例
@Controller
// HTTPリクエストが送られてくるたびにインスタンスが生成される
@Scope("request")
 public class Sample {
  …
}
```

#### @&#xFFF0;Primary 
優先的にDIを行いたいクラスに付与するアノテーション。

### 【Controllerクラスに関するアノテーション】
#### @&#xFFF0;RestController　
REST API 用のControllerクラスに付与するアノテーション。
クラスにつけることでそのクラス内のメソッドの戻り値がHTTPのレスポンスボディとして返される。

#### @&#xFFF0;RequestMapping
リクエストURLに対して、どのクラス・メソッドが処理を実行するか定義するアノテーション。クラスあるいはメソッドに付与する。
GET・POSTといったHTTPメソッドを指定する「method」属性とURLのパスを指定する「value」属性を指定できる。

```java:実装例
 // GETで"http://localhost:8080/sample" にアクセスすると、このメソッドが実行される
@RequestMapping(value = "sample", method = RequestMethod.GET)
 public String sample() {
  return "sample";
}
```
#### @&#xFFF0;GetMapping
@&#xFFF0;RequestMappingのGETリクエスト用アノテーション。
使用することで@&#xFFF0;RequestMappingで記述していたmethod属性を省略することができる。

#### @&#xFFF0;PostMapping
@&#xFFF0;RequestMappingのPOSTリクエスト用アノテーション。

#### @&#xFFF0;RequestParam
URLに含まれるクエリパラメータや、リクエストボディに含まれるパラメータを受け取るために使用するアノテーション。
下記属性を指定できる。
- name属性・value属性：リクエストパラメータを指定する。nameとvalueの役割に違いはない。
- required属性：パラメータはデフォルトでは必須になるため、パラメータの指定を任意にする場合、falseを指定する。
- defaultValue属性：リクエストパラメータが指定されなかった時のデフォルト値を指定する。

```java:実装例
@GetMapping(value = "/sample")
// 「name」というリクエストパラメータに紐づく値をsampleメソッドの引数nameに設定
// "http://localhost:8080/sample?name=AAA" でアクセスすると、nameには「AAA」が設定される
// "http://localhost:8080/sample" でアクセスすると、nameには「SAMPLE」が設定される
 public String sample(@RequestParam(name = "name", defaultValue = "SAMPLE", required = false) String name) {
  return name;
}
```

#### @&#xFFF0;PathVariable
URLに含まれる動的なパラメータを受け取るためのアノテーション。
@&#xFFF0;RequestParamはクエリパラメータから値を抽出するのに対し、@&#xFFF0;PathVariableはURLパスから値を抽出する。

<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710642/50f2b732-7825-31af-43ae-2e03cbbb93a2.png>



```java:実装例
@GetMapping(value = "/sample/{name}")
// "http://localhost:8080/sample/AAA" でアクセスすると、nameには「AAA」が設定される
 public String sample(@PathVariable("name") String name) {
  return name;
}
```

#### @&#xFFF0;ControllerAdvice
クラスに付与することで全てのControllerで共有するメソッドを用意することができるアノテーション。アプリケーション全体で共通化したい例外処理などに使用する。
以下のアノテーションがついたメソッドのみController間で共有できる。

#### @&#xFFF0;ExceptionHandler
メソッドに付与することで例外処理を実装できるアノテーション。
アノテーションの引数に例外クラスを指定することで、例外毎の処理を用意できる。

#### @&#xFFF0;InitBinder
@&#xFFF0;RequestParamや@&#xFFF0;PathVariableなどで受け取った値をオブジェクトにバインド（設定）する際に行う処理を定義できるアノテーション。
空文字の文字列項目をnullに変換する、文字列の空白を取り除く、といった処理を定義できる。

#### @&#xFFF0;ModelAttribute 
指定したクラスにリクエストパラメータをバインドするアノテーション。
メソッドまたはメソッドの引数に付与できる。

```java:SampleController.java
@RestController
 public class SampleController{
  @GetMapping("/")
    public String sample(@ModelAttribute SampleData sampleData) {
      return "form";
    }
 }
```
```java:SampleData.java
@Data 
 public class SampleData {
  private id;
  private password;
}
```
### 【Serviceクラスに関するアノテーション】
#### @&#xFFF0;Transactional
クラス・メソッドに付与することで、例外が発生すると自動でロールバックされるアノテーション。
非検査例外（RuntimeException）及びそのサブクラスが発生した場合はロールバック（実行前への巻き戻し）されるが、検査例外（Exception及びそのサブクラスでRuntimeException以外）が発生した場合は、ロールバックされずコミット（処理の確定）される。

### 【Repositoryクラスに関するアノテーション】
#### @&#xFFF0;Data
クラスに付与することで全フィールドに対してgetter/setterでアクセスすることができるようになるアノテーション。
hasCode()メソッドやequals()メソッド、toString()メソッドを自動生成してくれる。

#### @&#xFFF0;Entity
​​エンティティクラスであることを示すアノテーション。
データベースのテーブルとマッピングするクラスにつけつろ、クラス名と同じテーブル名を生成してくれたりする

#### @&#xFFF0;Table
テーブル名を設定するアノテーション。
通常はクラス名と同じテーブル名のデータをマッピングするため、クラス名とテーブル名が異なる場合はマッピングしたいテーブル名を設定する。

#### @&#xFFF0;Id
フィールドに付与し、主キーであることを示すアノテーション。

#### @&#xFFF0;Transient
マッピングしたくない（データベースに保存しない）フィールドに付与するアノテーション。

#### @&#xFFF0;Query
メソッドに付与することで任意のSQLを実行できるメソッドを用意できるアノテーション。
アノテーションの引数にクエリを書く。

#### @&#xFFF0;Modifying
@&#xFFF0;Queryアノテーションを使ってinsert・update・deleteをする際に必ず不要する必要があるアノテーション。

```java:実装例
@Modifying
@Query("update User"
        "set"
        "password = :password"
        "where"
        "id = :id")
public Integer updateUser(@Param("password") String password, @Param("id") String id) ;
```

#### @&#xFFF0;JoinColumn
テーブル結合時、条件となる結合先テーブルのカラム名を指定するためのアノテーション。
結合先の情報となるフィールドに付与する。
name属性に結合先のキーとなるカラム名を指定する。

#### @&#xFFF0;OneToOne
テーブルと結合先テーブルが一対一の関係の場合に付与するアノテーション。

#### @&#xFFF0;OneToMany
テーブルと結合先テーブルが一対多の関係の場合に付与するアノテーション。

#### @&#xFFF0;ManyToOne
テーブルと結合先テーブルが多対一の関係の場合に付与するアノテーション。

```java:実装例
@Entity
public class Club {
  @Id
  private long clubId;

  private String clubName;

  @OneToOne
  @JoinColumn(name = "clubId")
  // clubIdが一致するStudentエンティティを結合する 
  private Student student;
}
```

### 【バリデーションに関するアノテーション】
#### @&#xFFF0;Validated
バリデーション（入力チェック）を行いたいパラメータ・クラスに付与するアノテーション。

#### @&#xFFF0;GroupSequence
バリデーションの実行順を指定するアノテーション。
左に設定されたものから実行していく。

#### @&#xFFF0;DataTimeFormat
フォーマットを指定することで、受け取った値を日付型に変換するアノテーション。

#### @&#xFFF0;NumberFormat
フォーマットを指定することで、受け取った値を数値型に変換するアノテーション。

#### @&#xFFF0;NonNull
nullでないことをチェックするアノテーション。
※空文字・空白はOKになる

#### @&#xFFF0;NotEmpty
nullまたは空文字でないことをチェックするアノテーション。
※空白はOKになる

#### @&#xFFF0;NotBlank
null・空文字・空白でないことをチェックするアノテーション。

#### @&#xFFF0;Max
指定した値以下であるかをチェックするアノテーション。

#### @&#xFFF0;Min
指定した値以上であるかをチェックするアノテーション。

#### @&#xFFF0;Size
文字列の長さやListのsizeが指定した範囲内になるかチェックするアノテーション。

#### @&#xFFF0;AssertTrue
trueかどうかをチェックするアノテーション。

#### @&#xFFF0;AssertFalse
falseかどうかをチェックするアノテーション。

#### @&#xFFF0;Pattern
指定した正規表現に一致するかをチェックするアノテーション。

```java:SampleData.java
@Data
public class SampleData {
 @NotBlank
 private id;

 @NotBlank
 @Size(min = 5, max =20)
 private password;
}
```
```java:SampleController.java
@RestController
public class SampleController {
 @PostMapping
 public void create(@RequestBody @Validated SampleData data) {
  …
 }
}
```

### 【AOPに関するアノテーション】
#### @&#xFFF0;Aspect
横断的関心事を実装したメソッドであるAdviceを記述するAspectクラスに付与するアノテーション。

#### @&#xFFF0;Before
中心的関心事の呼び出し前に実行したいメソッドに付与するアノテーション。

#### @&#xFFF0;After
中心的関心事の呼び出し後に実行したいメソッドに付与するアノテーション。

#### @&#xFFF0;AfterReturning
中心的関心事が正常終了した後に実行したいメソッドに付与するアノテーション。

#### @&#xFFF0;Around
中心的関心事の呼び出し前・呼び出し後に実行したいメソッドに付与するアノテーション。

#### @&#xFFF0;AfterThrowing
中心関心事が例外をスローした後に実行するメソッドに付与するアノテーション。

#### @&#xFFF0;annotation
指定したアノテーションがついているメソッドを実行対象として指定するアノテーション。

```java:実装例
// @GetMappingが付与されたメソッドの呼び出し前に実行する
@Before("@annotation(org.springframework.web.bind.annotation.GetMapping)")
 public void sample() {
  …
}
```

#### @&#xFFF0;within
指定したアノテーションがついているクラスの全てのメソッドがAOPの対象となる。

```java:実装例
// @Controllerが付与されたクラスの全メソッドの呼び出し前に実行する
@Before("@within(org.springframework.stereotype.Controller)")
 public void sample() {
  …
}
```

### 【セキュリティに関するアノテーション】
#### @&#xFFF0;EnableWebSecurity
クラスに付与することでセキュリティ設定クラスを実装できるアノテーション。
実装時は、@&#xFFF0;Configurationをクラスに付与すること・WebSecurityConfigurerAdapterクラスを継承する必要がある。

## 参考文献
- [Spring解体新書第2版](https://amzn.asia/d/5kCJXRs)
- [Spring Framework超入門 優しくわかるWebアプリ開発](https://amzn.asia/d/6S4VXOg)
- [Springドキュメント](https://spring.pleiades.io/)