
レガシーなシステムでは何かを設定するたびに長いXMLファイルを書く必要がありました。(struts.xml や applicationContext.xml など) 現在はほぼほぼ Javaコードの上に @ から始まるアノテーションを1行書くだけで、裏側のフレームワークがそれを読み取って魔法のように処理を自動生成してくれます。今回はアノテーションについて簡単にお伝えします。
アノテーションとは?
アノテーションとは、一言でいうと「コードに付与する @ から始まる注釈・追加情報」です。@ から始まる記述は、 Javaソースコードの中でよく見かけることでしょう。アノテーションはプログラムの動作そのものを直接書くのではありません。特定の情報をコンパイラやフレームワークに伝える役割を持っています。
アノテーションの役割
アノテーションの役割は以下の3つです。
- コンパイラへの通知・チェック (Compiler instructions)
- ビルド時・デプロイ時の自動処理 (Build-time processing)
- 実行時の動作変更 (Runtime processing)
コンパイラへの通知・チェック
コードに間違いがないか、コンパイルするときにチェックさせます。 代表例が @Override です。これは「親クラスのメソッドを上書き (Override) しています」とコンパイラに伝えるもので、もしスペルミスなどで正しく上書きできていない場合は、コンパイルエラーとして教えてくれます。
ビルド時・デプロイ時の自動処理
ソフトウェアをビルド (JARファイルなどにまとめる工程) する際、アノテーションを検知して自動でソースコードや設定ファイルを生成するツールがあります。
実行時の動作変更
これがフレームワーク (Spring Bootなど) やライブラリ (Jacksonなど) で最もよく使われる強力な機能です。プログラムの実行時にアノテーションを読み取り、動作を裏側でガラリと変えることができます。
アノテーションの例
| @Override | メソッドを正しくオーバーライドしているかチェックする | 標準Javaのアノテーション |
| @Deprecated | 「このメソッドは古いため、将来削除される予定です (非推奨)」と警告を出す。 | 標準Javaのアノテーション |
| @JsonProperty(“キー名”) | Javaの変数名と、JSONのキー名が違う場合にマッピングする。 | Jackson のアノテーション |
| @JsonIgnore | 「この変数は秘密情報 (パスワードなど) なので、JSONにシリアライズさせない」という指定をする。 | Jackson のアノテーション |
| @RestController | 「このクラスはWebからのリクエストを受け付ける窓口 (Controller) です」とフレームワークに伝える。 | Spring Boot のアノテーション |
| @GetMapping(“/users”) | 「/users というURLにアクセスが来たら、このメソッドを実行する」というルーティング (Routing) を行う。 | Spring Boot のアノテーション |
アノテーションがないとどうなるか?
| アノテーションなし | アノテーションあり |
| Javaコードとは別のファイルに「クラスAの役割は〇〇、URLは▢▢…」と大量に書く必要があった。 | Javaコードのすぐ上に @GetMapping などと書くだけで完結する。 |
| デメリット: コードと設定が離れているため、修正漏れやタイポが起きやすく、管理が非常に大変だった。 | メリット: コードとその説明が1箇所にまとまるため、直感的で読みやすく、開発効率が劇的に向上した。 |
指定されたアノテーションがわからない場合の対処法
開発中に見知らぬアノテーションに出会うことがあります。そのときどうすればよいのかについては、以下の4ステップでお伝えします。
- IDEの機能を使い、ソースコード上で直接調べる
- 公式ドキュメント (JavaDoc) を検索する
- 技術ブログや解説サイトで「具体的な使い方」を見る
IDEの機能を使い、ソースコード上で直接調べる
まずはIDE・開発ツールの機能を使って、JavaDocを確認したり定義元にジャンプしたりすることができます。IDEによって操作が違うので手順は省略します。
公式ドキュメント (JavaDoc) を検索する
次はGoogleなどの検索エンジンで JavaDoc を検索するのがよいでしょう。Spring Boot GetMapping javadoc など javadoc を含んだワードで検索するのがコツです。
| パッケージ名 | そのアノテーションがどこに属しているか (例: org.springframework.web.bind.annotation.GetMapping) これにより、どのライブラリの機能なのかが確定します。 |
| 説明文 | そのアノテーションが「いつ」「何のために」使われるのかが英語で記載されています。翻訳されていることもあります。 |
技術ブログや解説サイトで「具体的な使い方」を見る
Javadoc でもわからない場合は、開発者が有志で書いているブログ記事を探します。Qiita, Zenn, Stack Overflow, Baeldung などで探すのもよいでしょう。「実際のコード例 (Code snippets)」を探します。周りのクラスやメソッドとどう組み合わせて使われているかを見ることで、役割が直感的に理解できます。
| GetMapping とは? | Spring BootというWebフレームワークが提供しているアノテーション |
| 役割 | ブラウザなどから「データを取得するリクエスト (HTTP GETリクエスト)」が送られてきたときに、どのメソッドに処理を振り分けるか (ルーティング) を決めるもの。 |
| よくある書き方は? | @GetMapping(“/users”) と書くと /users というURLにアクセスされたときに、その下のメソッドが自動実行される。 |
実演を通じてアノテーションを理解する
この記事をお読みの方は Lombok (ロンボック) というライブラリをご存じだと思います。実際にこの Lombok を使って、アノテーションを理解しましょう。Lombok については以下の記事をご確認ください。
まずは、Lombok を使えるようにするためにビルドツール maven の pom.xml に依存関係を以下のように記述しましょう。
<dependencies>
<!-- 他のライブラリの記述がここに並びます -->
<!-- Lombokの依存関係を追加 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>次に、Webシステムなどでよく使われる「商品」を表すクラスを例にします。Lombokのアノテーションがどのような役割を果たしているか、コード内のコメントと合わせて確認してください。
package com.example.project;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
/**
* 商品情報を管理するPOJO(シンプルなJavaオブジェクト)クラス
* クラスの上にLombokのアノテーションを並べることで、
* 大量のボイラープレートコード(決まりきったコード)を自動生成します。
*/
@Data // ① ゲッター、セッター、toString、equalsなどを一括自動生成
@NoArgsConstructor // ② 引数なしの「デフォルトコンストラクタ」を自動生成
@AllArgsConstructor // ③ すべての属性を引数に受け取る「フルコンストラクタ」を自動生成
public class Product {
// 【属性(フィールド)の定義】
private Long id;
private String name;
private int price;
}上記の Product クラスには、ソースコード上は属性(変数)しか書かれていません。
package com.example.project;
public class Main {
public static void main(String[] args) {
// 1. @AllArgsConstructor があるので、全属性を渡して一発でインスタンス化できる
Product item = new Product(1L, "こだわり珈琲豆", 1200);
// 2. @Data のおかげで、手書きしていない「セッター(setPrice)」が使える
item.setPrice(1500); // 価格を1500円に更新
// 3. @Data のおかげで、手書きしていない「ゲッター(getName)」が使える
System.out.println("商品名: " + item.getName());
// 4. @Data のおかげで、中身を綺麗に表示する「toString()」も自動実行される
// 出力結果: Product(id=1, name=こだわり珈琲豆, price=1500)
System.out.println(item);
}
}しかし、Lombokのアノテーションがあるおかげで、裏側でコードが生成されます。このことにより、上記のように普通にメソッドを呼び出すことが可能です。各アノテーションの詳しい説明は以下の通りです。
| @Data | このデータアノテーションは、Javaのデータ格納用クラスに必要な機能を丸ごとひっくるめて自動生成するよう、Lombokに指示を出します。具体的には、裏側で以下のコードを自動で付け足してくれています。 ・Getter / Setter: getId(), setId(), getName(), setName(), getPrice(), setPrice() などのデータの出し入れ用メソッド。 ・ToString: クラス名と現在の属性の値を文字列にしてくれる toString() メソッド。 |
| @NoArgsConstructor | 引数なしコンストラクタのこと。Javaのシステムや一部のライブラリ (例えば以前紹介したJSONライブラリのJacksonなど) は、オブジェクトを復元する際に「中身が空っぽのインスタンス」を一度作る必要があります。そのために必要な public Product() {} という空のコンストラクタを自動生成します。 |
| @AllArgsConstructor | 全引数コンストラクタのこと。新しくデータを組み立てるときに、new Product(1L, “名前”, 1200) のように、すべてのデータを1行でセットしてインスタンス化できるようにするためのコンストラクタを自動生成します。 |
Lombok アノテーションを使わずにこの Product クラスを書こうとすると、かなり大変です。コードを作成する必要があります。(手書き or IDEの自動生成) しかし、Lombokのアノテーションをクラスの上に3行置くだけで、本質的な「属性の定義」だけの非常に見やすいコードに収まっています。
コメント