自定义注解

简介: 本文介绍如何在Spring项目中通过AOP实现自定义注解,用于日志记录。结合User示例,演示注解定义、@Target与@Retention等元注解作用,并通过切面拦截注解方法,输出日志信息。该方式可扩展至权限、缓存、参数验证等场景,提升代码可读性与复用性。(238字)

前言
自定义注解目前在我使用过的项目中,主要用用作日志丰富,参数处理,其核心还是借助于Spring的AOP进行实现,本文将结合具体代码演示简单的自定义注解实现流程。
2.实现
2.1 定义User
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

private Integer id;

private String name;

}
2.2 定义UserDAO
@Component
public class UserDao {

public User findUserById(Integer id) {
    if(id > 10) {
        return null;
    }
    return new User(id, "user-" + id);
}

}
2.3 定义UserService
@Service
public class UserService {

private final UserDao userDao;

public UserService(UserDao userDao) {
    this.userDao = userDao;
}

public User findUserById(Integer id) {
    return userDao.findUserById(id);
}

}
2.4 定义Controller
@RequestMapping(value = "user/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public User findUser(@PathVariable("id") Integer id) {
return userService.findUserById(id);
}
此时浏览器访问:http://{domain}/user/1即可出现对应效果
{
"id": 1,
"name": "user-1"
}
2.5 定义自定义注解
import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomAnnotation {
String name() default "";
String value() default "";
}
说明:
● @interface 不是interface,是注解类 定义注解
● Documented
○ 这个Annotation可以被写入javadoc
● @Retention
○ 修饰注解,是注解的注解,称为元注解
○ SOURCE, // 编译器处理完Annotation后不存储在class中
○ CLASS, // 编译器把Annotation存储在class中,这是默认值
○ RUNTIME // 编译器把Annotation存储在class中,可以由虚拟机读取,反射需要
● @Target
○ 注解的作用目标
○ @Target(ElementType.TYPE) //接口、类、枚举、注解
○ @Target(ElementType.FIELD) //字段、枚举的常量
○ @Target(ElementType.METHOD) //方法
○ @Target(ElementType.PARAMETER) //方法参数
○ @Target(ElementType.CONSTRUCTOR) //构造函数
○ @Target(ElementType.LOCAL_VARIABLE) //局部变量
○ @Target(ElementType.ANNOTATION_TYPE) //注解
○ @Target(ElementType.PACKAGE) //包

● 可以定义多个方法,每个方法在使用时参照下面的Controller使用即可,实际就是类似于@PostMapping这样的注解中使用过的value,method,produces等,如下:

2.6 AOP+Controller使用自定义注解
@CustomAnnotation(name = "findUser", value = "根据ID查找用户")
@RequestMapping(value = "user/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public User findUser(@PathVariable("id") Integer id) {
return userService.findUserById(id);
}
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class TestLogAspect {

@Pointcut("@annotation(cn.test.CustomAnnotation)")
private void pointcut() {}

@Before("pointcut() && @annotation(annotation)")
public void advice(JoinPoint joinPoint, CustomAnnotation annotation) {
    System.out.println(
        "类名:["
        + joinPoint.getSignature().getDeclaringType().getSimpleName()
        + "],方法名:[" + joinPoint.getSignature().getName()
        + "]-日志内容-[" + annotation.value() + ", "+annotation.name()+ "]");
}

}
3.总结
自定义注解其核心是借助于:@Target 和 @Rentention,@Documented组合实现,其实现还是需要依赖于Spring的AOP进行具体体现,除了上面的用作日志拦截,还可以自定义:数据验证注解,权限注解,缓存注解等多种用途,但其实现基本都遵循上述步骤。

相关文章
|
数据安全/隐私保护
Spring-AOP切入点表达式详解
Spring-AOP切入点表达式详解
358 0
|
Linux 异构计算 Docker
实战 Google Colab,一起用 GPU
实战 Google Colab,一起用 GPU
946 0
|
5月前
|
安全 Java
告别繁琐Case:Java 17的Switch表达式让代码更优雅
告别繁琐Case:Java 17的Switch表达式让代码更优雅
|
2月前
|
人工智能 自然语言处理 前端开发
电商行业有哪些agent应用:从智能服务到数据决策的闭环实践(2026年新版)
2026年电商竞争逻辑将根本逆转:AI Agent正从概念走向实战。本文以阿里云瓴羊体系为例,详解Quick Service(超级客服)、Quick BI“智能小Q”与Data Agent(数据管家)如何协同构建“前端懂业务、中台秒决策、底层治数据”的智能闭环,推动行业迈向“智能驱动”新纪元。(239字)
|
4月前
|
存储 弹性计算 人工智能
2026年最新阿里云无影云电脑收费价格:企业版、个人版及免费版配置收费清单
阿里云无影云电脑2026年升级配置与计费体系,覆盖企业版、个人版及免费试用。企业版分四类,支持灵活时长包与高性能图形工作站;个人版推五档核时套餐,适配办公与游戏;新用户可享免费试用。按需选择,降本增效。
|
6月前
|
SQL 存储 关系型数据库
MySQL中到底什么是覆盖索引、索引下推?
覆盖索引指查询只需通过索引即可获取数据,无需回表,提升查询效率。索引下推则在索引遍历时提前过滤条件,减少回表次数,尤其适用于联合索引中部分字段无法使用的情况,二者均能显著降低I/O开销,提高查询性能。(238字)
708 1
|
10月前
|
人工智能 JavaScript 前端开发
js删除对象属性
本文介绍了JavaScript中删除对象属性及数组元素的多种方法,包括设置属性为undefined、使用delete操作符、对象解构、Reflect.deleteProperty方法以及数组的delete和splice操作。每种方法均有示例代码及关键特性说明,适用于不同场景下的属性或元素删除需求,帮助开发者更高效地处理对象和数组的操作。
385 0
js删除对象属性
|
12月前
|
存储 Java 数据库连接
Mybatisplus中的主要使用注解
3.有些注解需要配合其他配置使用。例如,@Version需要配合乐观锁插件使用,@EnumValue需要配合对应的TypeHandler使用。
526 11
|
供应链 NoSQL Java
用Redisson写一个库存扣减的方法
通过本文的介绍,我们详细讲解了如何使用Redisson实现一个简单的库存扣减功能。通过使用分布式锁,可以确保库存扣减操作的原子性和高效性。希望本文能帮助您更好地理解和应用Redisson,构建高效、可靠的库存管理系统。
544 15
|
JavaScript Java Spring
@Async异步失效的9种场景
在Spring中,启用@Async异步功能需要在启动类或配置类上使用`@EnableAsync`。若未使用此注解,@Async将无效。另外,内部方法调用(如在一个类的方法中调用另一个被@Async注解的方法)会导致异步功能失效,因为这不涉及Spring的AOP代理。此外,@Async方法必须是public,返回类型为void或Future,不能是static或final,且其所在的类需被@Service等注解以使Spring管理。如果使用@ComponentScan,确保正确扫描包含@Async类的包路径。
641 1

热门文章

最新文章