SpringBoot实战:手把手教你创建自定义注解

前言

在SpringBoot开发中,注解(Annotation)是简化配置、提升开发效率的利器。通过自定义注解,我们可以实现业务逻辑与基础功能的解耦,让代码更加优雅。本文将带你从零开始创建自定义注解,并结合AOP实现日志记录功能。


一、注解基础知识回顾

1.1 元注解

Java提供了用于定义注解的元注解:

  • @Target:指定注解作用范围(类、方法、字段等)

  • @Retention:指定注解生命周期(源码、编译期、运行时)

  • @Documented:包含在Javadoc中

  • @Inherited:允许子类继承

1.2 注解本质

注解本质是接口,通过反射机制在运行时获取并处理。


二、创建自定义注解

2.1 定义日志注解

@Target(ElementType.METHOD)  // 作用于方法
@Retention(RetentionPolicy.RUNTIME)  // 运行时生效
public @interface OperationLog {
    String module() default "";  // 模块名称
    String type() default "";   // 操作类型
    String description() default ""; // 操作描述
}

2.2 注解参数说明

  • 成员变量通过类型 名称()格式声明

  • default可设置默认值

  • 参数类型支持基本类型、String、Class、枚举等


三、结合AOP实现功能

3.1 添加AOP依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

3.2 实现切面逻辑

@Aspect
@Component
public class LogAspect {

    // 定义切点:拦截带有@OperationLog注解的方法
    @Pointcut("@annotation(com.example.demo.annotation.OperationLog)")
    public void logPointCut() {}

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        
        // 获取注解信息
        OperationLog logAnnotation = method.getAnnotation(OperationLog.class);
        String module = logAnnotation.module();
        String type = logAnnotation.type();
        String desc = logAnnotation.description();

        // 记录方法执行前日志
        System.out.println("【操作日志】模块:" + module 
                + " | 类型:" + type 
                + " | 描述:" + desc);
        
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();

        // 记录方法执行耗时
        System.out.println("方法执行耗时:" + (endTime - startTime) + "ms");
        return result;
    }
}

四、实际应用示例

4.1 在Controller中使用

@RestController
@RequestMapping("/user")
public class UserController {

    @OperationLog(module = "用户管理", type = "查询", description = "获取用户详情")
    @GetMapping("/detail/{id}")
    public User getUserDetail(@PathVariable Long id) {
        // 业务逻辑...
        return userService.getUserById(id);
    }
}

4.2 执行结果

【操作日志】模块:用户管理 | 类型:查询 | 描述:获取用户详情
方法执行耗时:58ms

五、扩展应用场景

  1. 权限校验@RequirePermission("user:delete")

  2. 接口限流@RateLimit(limit=100, period=60)

  3. 事务管理@DistributedTransaction

  4. 数据脱敏@SensitiveData

  5. 性能监控:统计方法执行时间


六、注意事项

  1. 确保切面类被Spring管理(使用@Component)

  2. 注意切入点表达式的正确性

  3. 优先使用环绕通知(@Around)获取完整控制权

  4. 合理处理异常避免影响业务逻辑


总结

通过自定义注解+AOP的组合,我们可以实现声明式的功能扩展。这种设计模式不仅提高了代码的可读性和可维护性,还能有效减少重复代码。建议大家在实际开发中根据业务需求灵活运用这种方案。


欢迎在评论区交流你的注解使用心得!
如果觉得有帮助,请点赞⭐收藏支持~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值