이러한 주석은 Spring Boot의 전체 프로젝트를 채웁니다.
그런데 이 주석이 어떤 문제를 해결하는지 아시나요?
처음부터 맞춤 주석이 도입된 이유는 무엇인가요?
맞춤 주석을 만드는 방법은 무엇인가요?
오늘 다룰 내용은 다음과 같습니다.
Spring Boot에서 주석은 단순한 메타데이터 추가 방법 그 이상입니다. 그들
Spring이 사용자 정의 주석을 도입하기 전에 개발자는 XML 구성 파일을 사용하여 이메일 검증과 같은 구성을 관리해야 했습니다.
XML 구성은 이메일 주소 확인과 같은 작업을 수행하는 데 필요한 빈, 유효성 검사기 및 기타 필수 구성 요소를 정의합니다.
다음은 Spring 애플리케이션에서 XML을 사용하여 이메일 검증을 구성한 방법에 대한 예입니다.
보시다시피, 수백 개의 클래스가 있고 그 중 많은 클래스가 서로 의존하는 경우 이것은 쉽게 악몽이 될 수 있습니다.
또한 개발자는 새 종속성을 추가해야 할 때마다 이 XML을 찾아야 했습니다.
Spring에서는 개발자가 코드에서 직접 주석을 사용할 수 있도록 하여 구성을 단순화하는 사용자 정의 주석을 도입했습니다.
이로 인해 광범위한 XML 구성의 필요성이 줄어들어 코드베이스가 더욱 깔끔하고 유지 관리가 쉬워졌습니다.
Spring의 사용자 정의 주석을 사용하면 선언적 접근 방식이 가능합니다.
개발자는 @Transactional, @Cacheable 또는 @Scheduled와 같은 주석을 사용하여 기본 논리를 작성하지 않고도 원하는 동작을 선언할 수 있습니다.
이렇게 하면 코드가 더 읽기 쉽고 유지 관리하기 쉬워집니다.
AOP(관점 지향 프로그래밍)와 함께 자주 사용되는 Spring의 사용자 정의 주석을 사용하면 개발자가 중앙 집중식으로 교차 편집 문제를 처리할 수 있습니다.
예를 들어 @Transactional 주석은 코드 전체에 트랜잭션 관리 논리를 분산시키지 않고 여러 메서드나 클래스에 걸쳐 트랜잭션을 관리합니다.
일반적인 동작을 캡슐화하여 상용구 코드의 필요성을 줄입니다.
예를 들어 @Autowired 주석은 종속성 주입을 단순화하여 명시적인 생성자나 설정자 메서드를 요구하지 않고 Spring이 자동으로 종속성을 주입할 수 있도록 합니다
@Autowired를 사용해야 하는지 아닌지는 다른 논의입니다.
Spring은 구성 및 교차 절단 문제를 주석으로 추상화하여 코드의 가독성을 향상시킵니다.
귀하와 동료 개발자는 주석을 보고 메서드나 클래스의 목적을 빠르게 이해할 수 있으며 주석은 코드베이스 전체에서 일관성을 강화하는 데 도움이 됩니다.
사용자 정의 주석을 사용하면 개발자가 특정 요구 사항에 맞는 주석을 생성하여 표준화된 방식으로 프레임워크의 기능을 확장할 수 있습니다.
이러한 유연성 덕분에 Spring은 여러 애플리케이션과 아키텍처 전반에 걸쳐 관련성과 강력함을 유지했습니다.
Spring의 BeanPostProcessor, Aspect 또는 사용자 정의 주석 처리 로직을 사용하여 주석을 처리하는 사용자 정의 로직을 생성할 수 있습니다.
정의된 대로 메서드, 필드 또는 클래스에 사용자 정의 주석을 적용합니다.
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); } }
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:
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.
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.
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.
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!