ホームページ >Java >&#&チュートリアル >Spring Boot でカスタム アノテーションを作成するための究極のガイド

Spring Boot でカスタム アノテーションを作成するための究極のガイド

PHPz
PHPzオリジナル
2024-08-25 18:01:02670ブラウズ

The Ultimate Guide to Create Custom Annotations in Spring Boot
このようなアノテーションは、Spring Boot のプロジェクト全体に埋め込まれます。

しかし、これらの注釈がどのような問題を解決するか知っていますか?

そもそもカスタム アノテーションが導入されたのはなぜですか?

カスタム注釈を作成するにはどうすればよいですか?

今日は以下について取り上げます:

  • カスタム注釈を作成する理由
  • これらの注釈を使用する主な利点は何ですか?
  • カスタム注釈を作成するにはどうすればよいですか?
  • アノテーション付きメソッドはどのように呼び出されますか?
  • カスタム注釈をいつ使用するか?
  • カスタム注釈を使用しない方が良い場合は?
  • カスタム注釈を使用するデメリットは何ですか?

?カスタム注釈を作成する理由

Spring Boot では、アノテーションはメタデータを追加する単なる手段ではありません。彼ら

  • 複雑なタスクを簡素化する
  • 定型コードを削減
  • コードの可読性を向上させる

Spring がカスタム アノテーションを導入する前は、開発者は XML 設定ファイルを使用して電子メール検証などの設定を管理する必要がありました。

XML 構成では、電子メール アドレスの検証などのタスクを実行するために Bean、バリデータ、およびその他の必要なコンポーネントが定義されます。

Spring アプリケーションで XML を使用して電子メール検証を構成する方法の例を次に示します。

The Ultimate Guide to Create Custom Annotations in Spring Boot

ご覧のとおり、これは何百ものクラスが存在し、その多くが相互に依存するという悪夢になる可能性があります。

これは、開発者が新しい依存関係を追加する必要があるたびに、この XML を調べなければならないことも意味しました。

カスタム注釈の主な利点

構成の簡素化

Spring ではカスタム アノテーションを導入し、開発者がコード内でアノテーションを直接使用できるようにすることで構成を簡素化しました。

これにより、広範な XML 構成の必要性が減り、コードベースがクリーンになり、保守が容易になりました。

宣言型プログラミングのサポート

Spring のカスタム アノテーションにより、宣言的なアプローチが可能になります。

開発者は、@Transactional、@Cacheable、@Scheduled などのアノテーションを使用して、基礎となるロジックを記述することなく、目的の動作を宣言できます。

これにより、コードがより読みやすく、保守しやすくなります。

横断的な懸念事項への対応

Spring のカスタム アノテーションは、アスペクト指向プログラミング (AOP) でよく使用され、開発者が横断的な問題を一元的に処理できるようにします。

たとえば、@Transactional アノテーションは、コード全体にトランザクション管理ロジックを分散させることなく、複数のメソッドまたはクラスにわたるトランザクションを管理します。

定型コードの削減

一般的な動作をカプセル化することで定型コードの必要性を減らします。

たとえば、@Autowired アノテーションは依存関係の注入を簡素化し、明示的なコンストラクターやセッター メソッドを必要とするのではなく、Spring が自動的に依存関係を注入できるようにします

@Autowired を使用する必要があるかどうかは別の議論です。

コードの可読性と一貫性の向上

設定と横断的な関心事を注釈に抽象化することで、Spring はコードの可読性を向上させます。

あなたと同僚の開発者は、アノテーションを確認することでメソッドやクラスの目的をすぐに理解でき、アノテーションはコードベース全体で一貫性を保つのに役立ちます。

フレームワークの柔軟性と拡張性

カスタム アノテーションを使用すると、開発者は特定のニーズに合わせたアノテーションを作成できるため、標準化された方法でフレームワークの機能を拡張できます。

この柔軟性により、Spring は複数のアプリケーションやアーキテクチャにわたって関連性と強力さを維持することができました。

?カスタム注釈を作成する方法

ステップ 1: 注釈を定義する

  • インターフェースを定義して新しいアノテーションを作成します。
  • @interface を使用して宣言します。
  • メタアノテーションを追加して、アノテーションがどのように動作するかを指定します。
package co.officegeek.tokenratelimiter;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)  // Annotation available at runtime
@Target(ElementType.METHOD)          // Can be applied to methods
public @interface LogExecutionTime {
}
  • @Target: アノテーションを使用できる場所 (メソッド、クラスなど) を示します。
  • @Retention: アノテーションが保持される期間 (実行時、コンパイル時など) を示します。

ステップ 2: 注釈を処理するアスペクトを作成する

Spring の BeanPostProcessor、Aspect、またはカスタム アノテーション処理ロジックを使用して、アノテーションを処理するカスタム ロジックを作成できます。

package co.officegeek.tokenratelimiter;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogExecutionTimeAspect {

    @Around("@annotation(LogExecutionTime)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long executionTime = System.currentTimeMillis() - start;

        System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
        return proceed;
    }
}

ステップ 3: 注釈を適用する

定義に従ってカスタム アノテーションをメソッド、フィールド、またはクラスに適用します。

package co.officegeek.tokenratelimiter;

import org.springframework.stereotype.Service;

@Service
public class TestService {

    @LogExecutionTime
    public void serve() throws InterruptedException {
        // Simulate some work
        Thread.sleep(2000);
    }
}

How It Works:

  • The @LogExecutionTime annotation doesn't cause any method to be called directly.
  • The Spring AOP framework detects that a method has the @LogExecutionTime annotation using reflection.
  • The LogExecutionTimeAspect aspect is configured to apply around advice when a method with the @LogExecutionTime annotation is called.
  • The logExecutionTime method in the aspect is executed before and after the annotated method (serve), logging the execution time.

The Ultimate Guide to Create Custom Annotations in Spring Boot


How does the annotated method get invoked?

When you apply a custom annotation to a method, class, or field, the annotation itself doesn't directly cause any method to be called.

Instead, the logic associated with the annotation is typically implemented using reflection or aspect-oriented programming (AOP) in frameworks like Spring.

Here's a breakdown of how the compiler and runtime environment know what method to call when an annotation is applied:

1. Compile-Time Processing (Annotation Processors)

Some annotations are handled at compile time by annotation processors.

Java's javax.annotation.processing package allows developers to create custom annotation processors that generate code, validate annotations, or even modify the abstract syntax tree (AST) of the code being compiled.

The annotation processor reads the annotations during compilation and executes code based on those annotations.

This can include generating new classes or methods that the code will use later.

The @Override annotation is a compile-time annotation that doesn't invoke a method but instead tells the compiler to check if the method actually overrides a superclass method.

How It Works:

  • You define a custom annotation processor by extending AbstractProcessor and overriding the process method.
  • The processor will be invoked by the compiler when it encounters your annotation, allowing you to generate code or perform other tasks.

2. Runtime Processing (Reflection)

Custom annotations can be processed at runtime using reflection.

The runtime system (e.g., a framework like Spring) uses reflection to detect the presence of annotations on methods, classes, or fields, and then applies the corresponding behavior.

A custom annotation like @LogExecutionTime doesn't directly trigger any method call.

Instead, an aspect or some other reflective mechanism checks for the presence of the annotation at runtime and then wraps the method call with additional logic.

How It Works:

  • At runtime, you use Java's reflection API to check if a method or class has a specific annotation using methods like isAnnotationPresent.
  • Once detected, you can invoke methods or execute logic associated with that annotation.  For example, if a method has a @LogExecutionTime annotation, you might measure the time before and after the method call.

3. Aspect-Oriented Programming (AOP)

In frameworks like Spring, AOP is commonly used to handle custom annotations.

AOP allows you to define "aspects" that can intercept method calls and perform additional processing before or after the method execution.

When the AOP framework (e.g. Spring AOP) detects an annotation, it triggers the execution of an advice method associated with the aspect.

This advice method contains the logic that the AOP framework executes when the annotated method is called.

A @Transactional annotation in Spring doesn't execute any logic by itself.

Instead, the Spring framework's AOP infrastructure intercepts calls to methods annotated with @Transactional and wraps them with transaction management logic.

How It Works:

  • You define an aspect class with advice methods that are associated with specific pointcuts (join points where you want to apply the advice).
  • The aspect uses annotations like @Around or @Before to specify when the advice should be executed.
  • The AOP framework ensures that when a method with a custom annotation is called, the corresponding advice is executed automatically.

Use Cases Where Custom Annotations Are a Good Approach

Cross-Cutting Concerns

Custom annotations are ideal for handling cross-cutting concerns like logging, security, transaction management, and caching.

These are concerns that affect multiple parts of an application but are not related to the core business logic.

上記の @LogExecutionTime アノテーションは、すべてのメソッドで使用でき、ビジネス ロジックを持たないため、良い例です。

宣言型プログラミング

どのように起こるかではなく、何が起こるべきかを指定したい場合、カスタム注釈を使用すると、これを行うためのクリーンで表現力豊かな方法が提供されます。

@Cacheable や @Retry などのアノテーションを使用すると、開発者は実装コードを手動で記述することなく、宣言的にキャッシュやロジックの再試行を有効にすることができます。

フレームワークまたはライブラリの統合

カスタム アノテーションは、使いやすいアノテーションの背後にある複雑さを隠すことで、フレームワークやライブラリの統合を簡素化できます。

Spring の @Autowired のようなアノテーションは、依存関係を手動でインスタンス化することなく注入するのに役立ちます。

複雑なロジックのカプセル化

複雑なロジックを再利用可能な方法でカプセル化する必要がある場合、カスタム アノテーションは、このロジックを適用するためのクリーンな API を提供できます。

@RateLimit のようなアノテーションは、メソッドの本体をこのロジックで混乱させることなく、メソッドの呼び出し回数を制限するロジックをカプセル化できます。

カスタム アノテーションを使用すべきではないユースケース

シンプルまたは一回限りのロジック

ロジックが単純な場合、または 1 か所にのみ適用する必要がある場合、カスタム アノテーションを作成するのは過剰であり、コードが不必要に複雑になる可能性があります。

動的な動作を必要とするロジック

アノテーションはコンパイル時に静的に定義されるため、実行時に動作を動的に決定する必要があるシナリオには適していません。

ユーザー入力または外部構成に基づいてメソッドの動作が変更される必要がある場合、カスタム アノテーションを使用してこれを処理すると、複雑な解決策が必要になる可能性があります。

ビジネスロジック

コア ビジネス ロジックをカスタム アノテーションに抽象化しないでください。これにより、ロジックの透明性が低下し、保守が困難になる可能性があります。

@ProcessOrder などのビジネス プロセスをカプセル化するためにアノテーションを使用すると、重要なビジネス ルールが隠蔽され、コードの理解と保守が困難になる可能性があります。

注釈間の複雑な相互作用

動作が複数のアノテーション間の複雑な相互作用に依存している場合、予期しない結果が生じ、コードの理解とデバッグが困難になる可能性があります。

同じメソッドに影響を与える複数のカスタム アノテーション (@Retry、@Cacheable、@LogExecutionTime など) を組み合わせると、予期しない動作が発生する可能性があり、管理が困難です

パフォーマンスが重要なコード

カスタム アノテーションはリフレクションまたはプロキシ メカニズムに依存することが多く、パフォーマンスのオーバーヘッドが発生する可能性があります。

コードのパフォーマンスが重要なセクションでは使用しないでください。

カスタム アノテーションを使用して、タイトなループで何百万回も呼び出されるメソッドにログを追加すると、パフォーマンスが大幅に低下する可能性があります。

?概要 - カスタム注釈を使用する場合

カスタム アノテーションは、ロギング、セキュリティ、トランザクション管理などの横断的な問題を処理するのに最適です。

これらは、アプリケーションの複数の部分に同じ動作を適用する必要があるシナリオにも最適です。

ただし、単純な 1 回限りのロジックの場合、またはきめ細かい制御と柔軟性が必要な場合は、カスタム アノテーションが最適なアプローチではない可能性があります。

実装を決定する前に、トレードオフを検討してください。

?最終的な考え

カスタム アノテーションは Spring Boot の強力なツールですが、他のツールと同様、慎重に使用する必要があります。

これらは、反復的なタスクを処理し、コードベース全体で一貫性を確保するクリーンで再利用可能な方法を提供します。

ただし、特に複雑さとパフォーマンスに関して、潜在的な欠点に注意してください。


??発表

私は、ソフトウェア開発者と意欲的なマイクロサービスアーキテクトを対象とした、Spring Boot と Bucket4j を使用したレート制限サービスの設計と実装に関する 10 日間のコホートベースのコースを開始します。

次のことを学びます:

✅ 本番環境に対応したマイクロサービスを設計して構築する方法

✅ レート制限アルゴリズムとその実装に関する深い知識

✅ Spring Boot の開発、テスト、コンテナ化のベスト プラクティス

しかし、それはまた

についてです

✅ プロジェクトを特定のタスクに分割する

✅ 自分自身に責任を持つ

✅ プロジェクトを適切に設計し構築する

ほとんどの企業に関連するユースケースであるマイクロサービスを設計および開発したいソフトウェア開発者を対象としています。

これは特に、「プロジェクトの経験」はないものの、多大な情熱と野心を持っている、ソフトウェア開発者のキャリアの初期の方に最適です。

これが役立つと思われる場合、または単に詳細を知りたい場合:

관심 등록하시면 워크숍 세부사항을 알려드리겠습니다.


이 내용은 내 하위 스택에 처음 게시되었습니다. 먼저 업데이트를 받으려면 내 Substack - Weekend Developer를 구독하세요.

당신이 작성한 코드에 대한 피드백이 필요한 개발자이신가요?

아니면 당신이 올바른 일을 할 수 있도록 누군가가 당신의 코드를 검토하길 원하시나요?

저는 사람들이 조기에 피드백을 받고 더 나은 코드를 작성할 수 있도록 무료 코드 검토 세션을 제공합니다

Twitter(X) 또는 LinkedIn으로 DM을 보내주시면 코드 작성에 도움을 드리겠습니다.

以上がSpring Boot でカスタム アノテーションを作成するための究極のガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。