首页> Java> java教程> 正文

在 Spring Boot 中创建自定义注释的终极指南

PHPz
发布: 2024-08-25 18:01:02
原创
411 人浏览过

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 自动注入依赖,而不需要显式的构造函数或 setter 方法

是否应该使用 @Autowired 这是一个不同的讨论。

提高代码可读性和一致性

Spring 通过将配置和横切关注点抽象为注解,提高了代码的可读性。

您和您的同行开发人员可以通过查看方法或类的注释来快速了解方法或类的用途,并且注释有助于增强整个代码库的一致性。

框架灵活性和可扩展性

自定义注释允许开发人员根据特定需求创建定制的注释,从而以标准化的方式扩展框架的功能。

这种灵活性帮助 Spring 在多个应用程序和架构中保持相关性和强大功能。

?如何创建自定义注释

第 1 步:定义注释

  • 通过定义接口创建新的注解。
  • 使用@interface来声明它。
  • 添加元注释来指定注释的行为方式。
雷雷
  • @Target:指示可以使用注解的位置(例如方法、类)。
  • @Retention:表示注释保留多长时间(例如,运行时、编译时)。

步骤 2:创建一个方面来处理注释

您可以使用 Spring 的 BeanPostProcessor、Aspect 或自定义注解处理逻辑创建自定义逻辑来处理注解。

雷雷

第 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這樣的註解可以封裝邏輯來限制方法被呼叫的次數,而不會用這個邏輯來擾亂方法的主體。

不應使用自訂註解的用例

簡單或一次性的邏輯

如果邏輯很簡單或只需要在一個地方應用,那麼創建自訂註解就太過分了,並且會使程式碼不必要地複雜化。

需要動態行為的邏輯

註解是在編譯時靜態定義的,不適合需要在執行時動態決定行為的場景。

如果方法的行為應根據使用者輸入或外部配置而改變,則使用自訂註解處理此問題可能會導致複雜的解決方案。

業務邏輯

核心業務邏輯不應該被抽象化為自訂註釋,因為這會使邏輯不那麼透明且難以維護。

使用@ProcessOrder這樣的註解來封裝業務流程可能會隱藏重要的業務規則,使程式碼更難理解和維護。

註解之間複雜的交互

如果行為依賴多個註釋之間的複雜交互,則可能會導致意外結果並使程式碼難以理解和調試。

組合影響相同方法的多個自訂註解(例如@Retry、@Cacheable、@LogExecutionTime)可能會導致不可預測的行為並且難以管理

效能關鍵程式碼

自訂註解通常依賴反射或代理機制,這會帶來效能開銷。

它們不應該用在程式碼的效能關鍵部分。

使用自訂註解向在緊密循環中呼叫數百萬次的方法添加日誌記錄可能會顯著降低效能。

?摘要 - 何時使用自訂註釋

自訂註解非常適合處理橫切問題,例如日誌記錄、安全性和事務管理。

它們也非常適合您需要在應用程式的多個部分應用相同行為的場景。

但是,對於簡單、一次性的邏輯,或需要細粒度控制和靈活性的情況,自訂註解可能不是最好的方法。

在決定實施之前請考慮權衡。

?最後的想法

自訂註解是 Spring Boot 武器庫中的強大工具,但像任何工具一樣,應該謹慎使用它們。

它們提供了一種乾淨、可重用的方式來處理重複性任務並在程式碼庫中強制執行一致性。

但請注意潛在的缺點,尤其是複雜性和性能方面。


??公告

我正在為軟體開發人員和有抱負的微服務架構師推出為期 10 天的隊列課程,介紹如何使用 Spring Boot 和 Bucket4j 設計和實現速率限制服務。

您將學到:

✅ 如何設計與建造可投入生產的微服務

✅ 深入了解速率限制演算法及其實現

✅ Spring Boot 開發、測試和容器化的最佳實踐

但這也是關於

✅ 將項目分解為具體任務

✅ 對自己負責

✅ 正確設計與建造專案

它針對的是想要設計和開發微服務的軟體開發人員,這是與大多數公司相關的用例。

特別適合那些處於軟體開發人員職業生涯早期的人,他們可能沒有“專案經驗”,但有大量的熱情和雄心。

如果您認為這對您有幫助,或者即使您只是想了解更多:

登記您的興趣,我會讓您知道研討會詳情。


這首先發佈在我的子堆疊上。訂閱我的 Substack - Weekend Developer 以第一時間獲取更新。

您是需要對您所寫的程式碼提供回饋的開發人員嗎?

或您是否希望有人審查您的程式碼以便您做正確的事情?

我幫助人們進行免費的程式碼審查會議,以便他們能夠儘早獲得回饋並編寫更好的程式碼

在 Twitter (X) 或 LinkedIn 上私訊我,我將協助您編寫程式碼。

以上是在 Spring Boot 中创建自定义注释的终极指南的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!