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

AOP实战案例

Spring AOP在实际项目中应用广泛,以下展示几个典型场景。

一、操作日志记录

Java
// 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
    String module();      // 模块名
    String operation();   // 操作描述
}

// 日志切面
@Aspect
@Component
@Slf4j
public class OperationLogAspect {

    @AfterReturning(pointcut = "@annotation(opLog)", returning = "result")
    public void recordLog(JoinPoint joinPoint, OperationLog opLog, Object result) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        // 保存日志到数据库
        SysLog sysLog = new SysLog();
        sysLog.setModule(opLog.module());
        sysLog.setOperation(opLog.operation());
        sysLog.setMethod(className + "." + methodName);
        sysLog.setParams(JSON.toJSONString(args));
        sysLog.setCreateTime(LocalDateTime.now());

        logService.save(sysLog);
        log.info("操作日志: {} - {}", opLog.module(), opLog.operation());
    }

    @AfterThrowing(pointcut = "@annotation(opLog)", throwing = "ex")
    public void recordError(JoinPoint joinPoint, OperationLog opLog, Exception ex) {
        log.error("操作异常: {} - {}, 异常: {}", opLog.module(), opLog.operation(), ex.getMessage());
    }
}

// 使用示例
@RestController
public class UserController {
    @OperationLog(module = "用户管理", operation = "新增用户")
    @PostMapping("/users")
    public Result addUser(@RequestBody User user) {
        return Result.success(userService.add(user));
    }
}

二、性能监控

Java
// 性能监控注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PerformanceMonitor {
    long threshold() default 1000; // 阈值(毫秒)
}

// 性能切面
@Aspect
@Component
@Slf4j
public class PerformanceAspect {

    @Around("@annotation(monitor)")
    public Object monitor(ProceedingJoinPoint pjp, PerformanceMonitor monitor) throws Throwable {
        String methodName = pjp.getSignature().toShortString();
        long start = System.currentTimeMillis();

        try {
            Object result = pjp.proceed();
            return result;
        } finally {
            long elapsed = System.currentTimeMillis() - start;
            if (elapsed > monitor.threshold()) {
                log.warn("性能告警: {} 耗时 {}ms, 超过阈值 {}ms",
                         methodName, elapsed, monitor.threshold());
            } else {
                log.debug("方法执行: {} 耗时 {}ms", methodName, elapsed);
            }
        }
    }
}

// 使用示例
@Service
public class OrderService {
    @PerformanceMonitor(threshold = 500)
    public Order createOrder(OrderRequest request) {
        // 业务逻辑
    }
}

三、权限校验

Java
// 权限注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
    String[] value();
}

// 权限切面
@Aspect
@Component
public class PermissionAspect {

    @Autowired
    private SecurityService securityService;

    @Before("@annotation(requirePermission)")
    public void checkPermission(JoinPoint jp, RequirePermission requirePermission) {
        String[] permissions = requirePermission.value();
        String userId = getCurrentUserId();

        for (String permission : permissions) {
            if (!securityService.hasPermission(userId, permission)) {
                throw new PermissionDeniedException(
                    "无权限: " + permission);
            }
        }
    }

    private String getCurrentUserId() {
        // 从SecurityContext获取当前用户ID
        return SecurityContextHolder.getContext()
                .getAuthentication().getName();
    }
}

// 使用示例
@RestController
public class AdminController {
    @RequirePermission("user:delete")
    @DeleteMapping("/users/{id}")
    public Result deleteUser(@PathVariable Long id) {
        userService.delete(id);
        return Result.success();
    }
}

四、防重复提交

Java
// 防重注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventDuplicate {
    int seconds() default 5;  // 防重时间窗口
    String key() default "";  // SpEL表达式
}

// 防重切面
@Aspect
@Component
@Slf4j
public class PreventDuplicateAspect {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Around("@annotation(prevent)")
    public Object prevent(ProceedingJoinPoint pjp, PreventDuplicate prevent) throws Throwable {
        String key = generateKey(pjp, prevent);
        String lockKey = "prevent:duplicate:" + key;

        Boolean acquired = redisTemplate.opsForValue()
                .setIfAbsent(lockKey, "1", prevent.seconds(), TimeUnit.SECONDS);

        if (Boolean.FALSE.equals(acquired)) {
            throw new BusinessException("请勿重复提交");
        }

        try {
            return pjp.proceed();
        } finally {
            redisTemplate.delete(lockKey);
        }
    }

    private String generateKey(JoinPoint jp, PreventDuplicate prevent) {
        String key = prevent.key();
        if (StringUtils.hasText(key)) {
            // 解析SpEL表达式
            return parseSpEL(jp, key);
        }
        // 默认使用方法签名+参数hash
        return jp.getSignature().toShortString() + Arrays.toString(jp.getArgs());
    }
}

五、统一异常处理

Java
// 异常处理切面
@Aspect
@Component
@Slf4j
public class ExceptionAspect {

    @AfterThrowing(pointcut = "execution(* com.example..service..*.*(..))",
                   throwing = "ex")
    public void handleServiceException(JoinPoint jp, Exception ex) {
        String method = jp.getSignature().toShortString();
        log.error("业务异常 - 方法: {}, 异常: {}", method, ex.getMessage());

        // 可选:发送告警通知
        if (ex instanceof BusinessException) {
            // 业务异常不告警
            return;
        }
        alertService.sendAlert(method, ex);
    }
}

要点总结

  • 日志记录:使用@AfterReturning/@AfterThrowing捕获执行结果
  • 性能监控:使用@Around环绕通知统计耗时
  • 权限校验:使用@Before前置通知拦截无权限请求
  • 防重复提交:结合Redis实现分布式锁
  • 统一异常处理:集中处理Service层异常

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

← 上一篇 AOP代理机制
下一篇 → Spring AOP原理
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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