”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 在 Spring Boot 中创建自定义注释的终极指南

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

发布于2024-11-05
浏览:963

The Ultimate Guide to Create Custom Annotations in Spring Boot
Such annotations fill the entire project in Spring Boot.

But do you know what problems these annotations solve?

Why were custom annotations introduced to begin with?

How to create custom annotations?

Today, I will cover:

  • Why create custom annotations?
  • What are the key benefits of using these annotations?
  • How to create custom annotations?
  • How does the annotated method get invoked?
  • When to use custom annotations?
  • When not to use custom annotations?
  • What are the disadvantages of using custom annotations?

? Why Create Custom Annotations?

In Spring Boot, annotations are more than just a way to add metadata. They

  • Simplify complex tasks
  • Reduce boiler-plate code
  • Enhance code-readability

Before Spring introduced custom annotations, developers had to manage configurations like email validation using XML configuration files.

The XML configuration would define beans, validators, and other necessary components to perform tasks such as validating email addresses.

Here's an example of how email validation might have been configured using XML in a Spring application:

The Ultimate Guide to Create Custom Annotations in Spring Boot

As you can see, this can easily become a nightmare where there are hundreds of classes with many of them relying on each other.

It also meant a developer had to go look up this XML every time they had to add a new dependency.

Key Benefits of Custom Annotations

Simplification of Configuration

Spring introduced custom annotations to simplify configuration by allowing developers to use annotations directly in their code.

This reduced the need for extensive XML configuration, making the codebase cleaner and easier to maintain.

Support for Declarative Programming

Custom annotations in Spring enable a declarative approach.

Developers can use annotations like @Transactional, @Cacheable, or @Scheduled to declare desired behaviors without writing the underlying logic.

This results in more readable and maintainable code.

Handling Cross-Cutting Concerns

Spring's custom annotations, often used with Aspect-Oriented Programming (AOP), allow developers to handle cross-cutting concerns in a centralized manner.

For example, the @Transactional annotation manages transactions across multiple methods or classes without scattering transaction management logic throughout the code.

Reducing Boilerplate Code

It reduces the need for boilerplate code by encapsulating common behaviours.

For instance, the @Autowired annotation simplifies dependency injection, allowing Spring to automatically inject dependencies, rather than requiring explicit constructor or setter methods

It is a different discussion whether you should be using @Autowired or not.

Improving Code Readability and Consistency

By abstracting configuration and cross-cutting concerns into annotations, Spring improves the readability of the code.

You and your peer developers can quickly understand the purpose of a method or class by looking at its annotations, and annotations help enforce consistency across the codebase.

Framework Flexibility and Extensibility

Custom annotations allow developers to create their annotations tailored to specific needs, thus extending the framework's functionality in a standardized way.

This flexibility has helped Spring remain relevant and powerful across multiple applications and architectures.

? How to Create a Custom Annotation

Step 1: Define the Annotation

  • Create a new annotation by defining an interface.
  • Use @interface to declare it.
  • Add meta-annotations to specify how the annotation should behave.
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: Indicates where the annotation can be used (e.g., methods, classes).
  • @Retention: Indicates how long the annotation is retained (e.g., runtime, compile-time).

Step 2: Create an Aspect to Handle the Annotation

You can create a custom logic to process the annotation using Spring's BeanPostProcessor, Aspect, or custom annotation processing logic.

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;
    }
}

Step 3: Apply the Annotation

Apply your custom annotation to methods, fields, or classes as defined.

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.

The @LogExecutionTime annotation above is a good example as that can be used across all the methods and it does not have any business logic.

Declarative Programming

When you want to specify what should happen rather than how it should happen, custom annotations provide a clean and expressive way to do this.

Annotations like @Cacheable or @Retry allow developers to enable caching or retry logic declaratively, without writing the implementation code manually.

Framework or Library Integration

Custom annotations can simplify the integration of frameworks or libraries by hiding the complexity behind an easy-to-use annotation.

Annotations like @Autowired in Spring help in injecting dependencies without having to manually instantiate them.

Encapsulation of Complex Logic

When complex logic needs to be encapsulated in a reusable way, custom annotations can provide a clean API for applying this logic.

An annotation like @RateLimit could encapsulate logic to limit the number of times a method can be called, without cluttering the method's body with this logic.

Use Cases Where Custom Annotations Should Not Be Used

Simple or One-Off Logic

If the logic is simple or only needs to be applied in a single place, creating a custom annotation is overkill and can unnecessarily complicate the code.

Logic That Requires Dynamic Behavior

Annotations are statically defined at compile-time, making them unsuitable for scenarios where behaviour needs to be dynamically determined at runtime.

If a method's behaviour should change based on user input or external configuration, handling this with custom annotations can lead to complex solutions.

Business Logic

Core business logic should not be abstracted into custom annotations, as this can make the logic less transparent and harder to maintain.

Using an annotation to encapsulate a business process like @ProcessOrder might hide important business rules, making the code harder to understand and maintain.

Complex Interactions Between Annotations

If the behavior depends on complex interactions between multiple annotations, it can lead to unexpected results and make the code difficult to understand and debug.

Combining multiple custom annotations that affect the same method (e.g., @Retry, @Cacheable, @LogExecutionTime) can result in unpredictable behavior and is difficult to manage

Performance-Critical Code

Custom annotations often rely on reflection or proxy mechanisms, which can introduce performance overhead.

They should not be used in performance-critical sections of code.

Using a custom annotation to add logging to a method that is called millions of times in a tight loop could significantly degrade performance.

? Summary - When to Use Custom Annotations

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

They're also great for scenarios where you need to apply the same behaviour across multiple parts of your application.

However, for simple, one-off logic, or where fine-grained control and flexibility are required, custom annotations might not be the best approach.

Consider the trade-offs before you decide to implement them.

? Final Thoughts

Custom annotations are a powerful tool in your Spring Boot arsenal, but like any tool, they should be used judiciously.

They offer a clean, reusable way to handle repetitive tasks and enforce consistency across your codebase.

But be mindful of the potential downsides, especially for complexity and performance.


?? Announcement

I am launching a 10-day cohort-based course for software developers and aspiring microservices architects on designing and implementing rate-limiting service using Spring Boot and Bucket4j.

You'll learn:

✅ How to design and build a production-ready microservice

✅ In-depth knowledge of rate-limiting algorithms and their implementation

✅ Best practices in Spring Boot development, testing, and containerisation

But it is also about

✅ breaking down the project into specific tasks

✅ Being accountable to yourself

✅ Designing and Building the project right

It is targeted at software developers who want to design and develop a microservice which is a use case relevant to most companies.

It's ESPECIALLY for those earlier in their software developer career who might not have "project experience" but tons of passion and ambition.

If this is something that you think will help you or even if you are just curious to know more:

Register your interest and I will let you know the workshop details.


This was first published on my Substack. Subscribe to my Substack - Weekend Developer to get updates first.

Are you a developer who needs feedback on the code you write?

Or do you want someone to review your code so that you are doing the right things?

I help people with free code review sessions so that they can get early feedback and write better code

DM me on Twitter (X) or on LinkedIn and I will help you with your code.

版本声明 本文转载于:https://dev.to/dishitdevasia/the-ultimate-guide-to-create-custom-annotations-in-spring-boot-fpa?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    为有效的slug生成首先,该函数用指定的分隔符替换所有非字母或数字字符。此步骤可确保slug遵守URL惯例。随后,它采用ICONV函数将文本简化为us-ascii兼容格式,从而允许更广泛的字符集合兼容性。接下来,该函数使用正则表达式删除了不需要的字符,例如特殊字符和空格。此步骤可确保slug仅包含...
    编程 发布于2025-04-18
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。要解决此问题并确保在后续页面访问中执行脚本,Firefox用户应设置一个空功能。 警报'); }; alert('inline Alert')...
    编程 发布于2025-04-18
  • 如何在其容器中为DIV创建平滑的左右CSS动画?
    如何在其容器中为DIV创建平滑的左右CSS动画?
    通用CSS动画,用于左右运动 ,我们将探索创建一个通用的CSS动画,以向左和右移动DIV,从而到达其容器的边缘。该动画可以应用于具有绝对定位的任何div,无论其未知长度如何。问题:使用左直接导致瞬时消失 更加流畅的解决方案:混合转换和左 [并实现平稳的,线性的运动,我们介绍了线性的转换。这...
    编程 发布于2025-04-18
  • 您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    您可以使用CSS在Chrome和Firefox中染色控制台输出吗?
    在javascript console 中显示颜色是可以使用chrome的控制台显示彩色文本,例如红色的redors,for for for for错误消息?回答是的,可以使用CSS将颜色添加到Chrome和Firefox中的控制台显示的消息(版本31或更高版本)中。要实现这一目标,请使用以下模...
    编程 发布于2025-04-18
  • 如何将MySQL数据库添加到Visual Studio 2012中的数据源对话框中?
    如何将MySQL数据库添加到Visual Studio 2012中的数据源对话框中?
    在Visual Studio 2012 尽管已安装了MySQL Connector v.6.5.4,但无法将MySQL数据库添加到实体框架的“ DataSource对话框”中。为了解决这一问题,至关重要的是要了解MySQL连接器v.6.5.5及以后的6.6.x版本将提供MySQL的官方Visual...
    编程 发布于2025-04-18
  • 在C#中如何高效重复字符串字符用于缩进?
    在C#中如何高效重复字符串字符用于缩进?
    在基于项目的深度下固定字符串时,重复一个字符串以进行凹痕,很方便有效地有一种有效的方法来返回字符串重复指定的次数的字符串。使用指定的次数。 constructor 这将返回字符串“ -----”。 字符串凹痕= new String(' - ',depth); console.Wr...
    编程 发布于2025-04-18
  • 查找当前执行JavaScript的脚本元素方法
    查找当前执行JavaScript的脚本元素方法
    如何引用当前执行脚本的脚本元素在某些方案中理解问题在某些方案中,开发人员可能需要将其他脚本动态加载其他脚本。但是,如果Head Element尚未完全渲染,则使用document.getElementsbytagname('head')[0] .appendChild(v)的常规方...
    编程 发布于2025-04-18
  • 如何克服PHP的功能重新定义限制?
    如何克服PHP的功能重新定义限制?
    克服PHP的函数重新定义限制在PHP中,多次定义一个相同名称的函数是一个no-no。尝试这样做,如提供的代码段所示,将导致可怕的“不能重新列出”错误。 但是,PHP工具腰带中有一个隐藏的宝石:runkit扩展。它使您能够灵活地重新定义函数。 runkit_function_renction_re...
    编程 发布于2025-04-18
  • 在Python中如何创建动态变量?
    在Python中如何创建动态变量?
    在Python 中,动态创建变量的功能可以是一种强大的工具,尤其是在使用复杂的数据结构或算法时,Dynamic Variable Creation的动态变量创建。 Python提供了几种创造性的方法来实现这一目标。利用dictionaries 一种有效的方法是利用字典。字典允许您动态创建密钥并分...
    编程 发布于2025-04-18
  • 使用jQuery如何有效修改":after"伪元素的CSS属性?
    使用jQuery如何有效修改":after"伪元素的CSS属性?
    在jquery中了解伪元素的限制:访问“ selector 尝试修改“:”选择器的CSS属性时,您可能会遇到困难。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    编程 发布于2025-04-18
  • FastAPI自定义404页面创建指南
    FastAPI自定义404页面创建指南
    response = await call_next(request) if response.status_code == 404: return RedirectResponse("https://fastapi.tiangolo.com") else: ...
    编程 发布于2025-04-18
  • 如何同步迭代并从PHP中的两个等级阵列打印值?
    如何同步迭代并从PHP中的两个等级阵列打印值?
    同步的迭代和打印值来自相同大小的两个数组使用两个数组相等大小的selectbox时,一个包含country代码的数组,另一个包含乡村代码,另一个包含其相应名称的数组,可能会因不当提供了exply for for for the uncore for the forsion for for ytry...
    编程 发布于2025-04-18
  • 为什么PHP的DateTime :: Modify('+1个月')会产生意外的结果?
    为什么PHP的DateTime :: Modify('+1个月')会产生意外的结果?
    使用php dateTime修改月份:发现预期的行为在使用PHP的DateTime类时,添加或减去几个月可能并不总是会产生预期的结果。正如文档所警告的那样,“当心”这些操作的“不像看起来那样直观。 考虑文档中给出的示例:这是内部发生的事情: 现在在3月3日添加另一个月,因为2月在2001年只有2...
    编程 发布于2025-04-18
  • 如何在Java的全屏独家模式下处理用户输入?
    如何在Java的全屏独家模式下处理用户输入?
    Handling User Input in Full Screen Exclusive Mode in JavaIntroductionWhen running a Java application in full screen exclusive mode, the usual event ha...
    编程 发布于2025-04-18
  • 如何实时捕获和流媒体以进行聊天机器人命令执行?
    如何实时捕获和流媒体以进行聊天机器人命令执行?
    在开发能够执行命令的chatbots的领域中,实时从命令执行实时捕获Stdout,一个常见的需求是能够检索和显示标准输出(stdout)在cath cath cant cant cant cant cant cant cant cant interfaces in Chate cant inter...
    编程 发布于2025-04-18

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3