全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 10 分钟 ✍️ juanwangdev

Spring Boot自定义注解与AOP结合

自定义注解结合AOP可优雅实现横切关注点。

AOP依赖配置

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

日志记录注解

定义注解

Java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogRecord {
    String operation();      // 操作描述
    String module();         // 模块名称
    boolean saveResult() default true;
}

定义切面

Java
@Aspect
@Component
@Slf4j
public class LogRecordAspect {

    @Around("@annotation(logRecord)")
    public Object around(ProceedingJoinPoint joinPoint,
                         LogRecord logRecord) throws Throwable {

        // 方法信息
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        // 前置日志
        log.info("开始执行 {}.{} - 模块:{}, 操作:{}, 参数:{}",
            className, methodName,
            logRecord.module(), logRecord.operation(),
            JsonUtil.toJson(args));

        long startTime = System.currentTimeMillis();

        try {
            Object result = joinPoint.proceed();

            // 成功日志
            log.info("执行成功 {}.{} - 耗时:{}ms, 结果:{}",
                className, methodName,
                System.currentTimeMillis() - startTime,
                logRecord.saveResult() ? JsonUtil.toJson(result) : "已忽略");

            return result;

        } catch (Exception e) {
            // 异常日志
            log.error("执行异常 {}.{} - 耗时:{}ms, 异常:{}",
                className, methodName,
                System.currentTimeMillis() - startTime,
                e.getMessage(), e);
            throw e;
        }
    }
}

使用注解

Java
@Service
public class OrderService {

    @LogRecord(module = "订单", operation = "创建订单")
    public Order createOrder(OrderDTO dto) {
        // 业务逻辑
    }
}

权限校验注解

Java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
    String[] value();
    Logical logical() default Logical.AND;
}

public enum Logical {
    AND, OR
}

@Aspect
@Component
public class PermissionAspect {

    @Autowired
    private SecurityService securityService;

    @Before("@annotation(requirePermission)")
    public void checkPermission(RequirePermission requirePermission) {
        String[] permissions = requirePermission.value();
        boolean hasPermission;

        if (requirePermission.logical() == Logical.AND) {
            hasPermission = securityService.hasAllPermissions(permissions);
        } else {
            hasPermission = securityService.hasAnyPermission(permissions);
        }

        if (!hasPermission) {
            throw new AccessDeniedException("权限不足");
        }
    }
}

// 使用
@RequirePermission(value = {"user:read", "user:write"}, logical = Logical.OR)
public void updateUser(User user) {
    // 业务逻辑
}

性能监控注解

Java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PerformanceMonitor {
    long threshold() default 1000; // 阈值ms
}

@Aspect
@Component
public class PerformanceAspect {

    @Autowired
    private MeterRegistry meterRegistry;

    @Around("@annotation(monitor)")
    public Object monitor(ProceedingJoinPoint joinPoint,
                          PerformanceMonitor monitor) throws Throwable {

        long start = System.currentTimeMillis();

        try {
            return joinPoint.proceed();
        } finally {
            long duration = System.currentTimeMillis() - start;

            // 记录指标
            Timer.builder("method.execution")
                .tag("class", joinPoint.getTarget().getClass().getSimpleName())
                .tag("method", joinPoint.getSignature().getName())
                .register(meterRegistry)
                .record(duration, TimeUnit.MILLISECONDS);

            // 超时告警
            if (duration > monitor.threshold()) {
                log.warn("方法执行超时: {}.{} 耗时:{}ms",
                    joinPoint.getTarget().getClass().getSimpleName(),
                    joinPoint.getSignature().getName(),
                    duration);
            }
        }
    }
}

重试注解

Java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {
    int maxAttempts() default 3;
    long delay() default 1000;
    Class<? extends Exception>[] retryFor() default {Exception.class};
}

@Aspect
@Component
public class RetryAspect {

    @Around("@annotation(retry)")
    public Object retry(ProceedingJoinPoint joinPoint,
                        Retry retry) throws Throwable {

        int attempts = 0;
        Exception lastException;

        while (attempts < retry.maxAttempts()) {
            try {
                return joinPoint.proceed();
            } catch (Exception e) {
                lastException = e;
                attempts++;

                if (!shouldRetry(e, retry.retryFor())) {
                    throw e;
                }

                if (attempts < retry.maxAttempts()) {
                    Thread.sleep(retry.delay());
                    log.warn("重试第{}次: {}", attempts, e.getMessage());
                }
            }
        }

        throw lastException;
    }

    private boolean shouldRetry(Exception e, Class<? extends Exception>[] retryFor) {
        for (Class<? extends Exception> ex : retryFor) {
            if (ex.isInstance(e)) {
                return true;
            }
        }
        return false;
    }
}

注解继承处理

Java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Auditable {
    String action();
}

// 切面处理类注解
@Around("@within(auditable) || @annotation(auditable)")
public Object audit(ProceedingJoinPoint joinPoint, Auditable auditable) {
    // 处理逻辑
}

要点总结

  • 注解定义需指定@Target和@Retention
  • 切面使用@Around等通知类型拦截
  • ProceedingJoinPoint获取方法上下文
  • 合理设计注解属性提高灵活性

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring Boot自定义健康指示器
下一篇 → ApplicationContext 创建与刷新
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库