kfyty725/loveqq-framework的AOP通知:@Around注解使用技巧

kfyty725/loveqq-framework的AOP通知:@Around注解使用技巧

【免费下载链接】loveqq-framework 全新轻量级 ioc/aop/javafx 框架,更小,更强大。 该框架基本实现自我配置,具有更强大的复杂的条件bean注册推断,全框架复合注解支持;统一命令式/响应式编程风格,包含过滤器、拦截器等;提供 javafx mvvm 框架,可实现模型-数据的双向绑定,父子窗口生命周期绑定及监听;提供动态数据源配置支持;提供注解式缓存支持;默认提供 jar 包瘦身方式打包,支持 jar-index 启动。 【免费下载链接】loveqq-framework 项目地址: https://gitcode.com/kfyty725/loveqq-framework

一、AOP与@Around注解基础

1.1 AOP核心概念

AOP(Aspect-Oriented Programming,面向切面编程)是一种通过横切关注点分离来提高代码模块化的技术。在loveqq-framework中,AOP主要通过以下核心组件实现:

组件作用
Join Point(连接点)程序执行过程中的特定点,如方法调用或异常抛出
Pointcut(切入点)匹配连接点的表达式,用于定义哪些方法需要被增强
Advice(通知)切面在特定连接点执行的动作,包括@Around、@Before、@After等
Aspect(切面)包含切入点和通知的模块化单元

1.2 @Around注解的独特价值

@Around是功能最强大的通知类型,它可以:

  • 完全控制目标方法的执行(决定是否执行、何时执行、执行前后的逻辑)
  • 修改目标方法的参数和返回值
  • 捕获并处理目标方法抛出的异常

与其他通知类型的对比:

mermaid

二、@Around注解的实现原理

2.1 核心类结构

loveqq-framework的AOP模块通过以下类实现@Around注解功能:

mermaid

关键代码实现(AspectJMethodAroundAdvice.java):

@Override
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    Signature signature = pjp.getSignature();
    return this.invokeAdviceMethod(((MethodSignature) signature).getMethod(), pjp, null, null);
}

2.2 执行流程

mermaid

三、@Around注解实战技巧

3.1 基础用法:性能监控切面

@Aspect
@Component
public class PerformanceMonitorAspect {
    private static final Logger logger = LoggerFactory.getLogger(PerformanceMonitorAspect.class);

    @Around("execution(* com.kfyty.service.*Service.*(..))")
    public Object monitorPerformance(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        try {
            // 执行目标方法
            return pjp.proceed();
        } finally {
            long costTime = System.currentTimeMillis() - startTime;
            logger.info("Method [{}] executed in {}ms", 
                       pjp.getSignature().getName(), costTime);
            
            // 性能告警
            if (costTime > 1000) {
                logger.warn("Method [{}] execution exceeds 1s", 
                           pjp.getSignature().getName());
            }
        }
    }
}

3.2 参数修改与结果增强

@Around("execution(* com.kfyty.service.UserService.query(..)) && args(id)")
public Object enhanceQuery(ProceedingJoinPoint pjp, Long id) throws Throwable {
    // 参数验证与修改
    if (id == null || id <= 0) {
        throw new IllegalArgumentException("用户ID必须为正整数");
    }
    
    // 执行目标方法
    User user = (User)pjp.proceed(new Object[]{id});
    
    // 结果增强
    if (user != null) {
        user.setLastQueryTime(new Date());
        user.setQueryCount(user.getQueryCount() + 1);
    }
    
    return user;
}

3.3 异常处理与恢复机制

@Around("execution(* com.kfyty.service.PaymentService.process(..))")
public Object handlePaymentException(ProceedingJoinPoint pjp) throws Throwable {
    PaymentRequest request = (PaymentRequest)pjp.getArgs()[0];
    int retryCount = 3;
    
    while (retryCount-- > 0) {
        try {
            return pjp.proceed();
        } catch (NetworkException e) {
            logger.warn("支付请求网络异常,剩余重试次数: {}, 请求ID: {}", 
                       retryCount, request.getRequestId(), e);
            if (retryCount == 0) {
                // 记录失败请求,以便后续处理
                paymentFailureQueue.offer(request);
                throw new ServiceUnavailableException("支付服务暂时不可用,请稍后重试");
            }
            Thread.sleep(1000 * (4 - retryCount)); // 指数退避策略
        }
    }
    
    throw new IllegalStateException("支付处理失败");
}

3.4 条件执行:动态开关控制

@Around("@annotation(com.kfyty.annotation.FeatureSwitch) && @annotation(switch)")
public Object featureSwitchControl(ProceedingJoinPoint pjp, FeatureSwitch sw) throws Throwable {
    String featureKey = sw.value();
    boolean enabled = featureSwitchService.isEnabled(featureKey);
    
    if (enabled) {
        return pjp.proceed();
    }
    
    if (sw.fallbackMethod().isEmpty()) {
        return sw.defaultValue();
    }
    
    // 调用 fallback 方法
    return invokeFallbackMethod(pjp, sw.fallbackMethod());
}

四、高级特性与最佳实践

4.1 与其他通知的协同使用

@Aspect
@Component
public class ComprehensiveAspect {
    @Before("execution(* com.kfyty.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        logger.info("方法调用前: {}", joinPoint.getSignature().getName());
    }
    
    @Around("execution(* com.kfyty.service.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        try {
            return pjp.proceed();
        } finally {
            logger.info("方法执行时间: {}ms", System.currentTimeMillis() - startTime);
        }
    }
    
    @AfterReturning("execution(* com.kfyty.service.*.*(..))")
    public void logAfterReturning(JoinPoint joinPoint) {
        logger.info("方法调用成功: {}", joinPoint.getSignature().getName());
    }
}

执行顺序:@Around前置逻辑 → @Before → 目标方法 → @Around后置逻辑 → @AfterReturning

4.2 性能优化建议

  1. 缩小切入点范围

    // 不佳
    @Around("execution(* com.kfyty..*(..))")
    
    // 推荐
    @Around("execution(* com.kfyty.service.order.OrderService.createOrder(..))")
    
  2. 避免在通知中执行耗时操作

    • 复杂逻辑异步处理
    • 避免循环和递归调用
  3. 使用编译时增强

    <plugin>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.9.7</version>
        <executions>
            <execution>
                <goals>
                    <goal>compile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

4.3 常见陷阱与解决方案

问题解决方案
忘记调用pjp.proceed()始终确保在@Around通知中调用proceed()方法
多次调用proceed()使用if (!proceeded) { result = pjp.proceed(); proceeded = true; }
参数修改无效使用pjp.proceed(newArgs)传递修改后的参数
异常吞噬始终记录异常并根据需要重新抛出

五、总结与扩展

@Around注解作为loveqq-framework AOP模块中最强大的通知类型,为开发者提供了全方位的方法增强能力。通过灵活运用@Around,可以实现性能监控、异常处理、功能开关、缓存控制等多种横切关注点功能。

5.1 典型应用场景回顾

mermaid

5.2 未来扩展方向

  1. 响应式编程支持:结合loveqq-mvc-reactor模块,提供响应式AOP支持
  2. 分布式追踪集成:与SkyWalking、Zipkin等分布式追踪系统无缝集成
  3. AI辅助优化:基于运行时数据自动优化切入点和通知逻辑

通过掌握@Around注解的使用技巧,开发者可以充分发挥AOP的威力,编写更简洁、更健壮、更易于维护的代码。建议在实际项目中结合具体业务场景,灵活运用本文介绍的各种技巧,以达到最佳效果。

【免费下载链接】loveqq-framework 全新轻量级 ioc/aop/javafx 框架,更小,更强大。 该框架基本实现自我配置,具有更强大的复杂的条件bean注册推断,全框架复合注解支持;统一命令式/响应式编程风格,包含过滤器、拦截器等;提供 javafx mvvm 框架,可实现模型-数据的双向绑定,父子窗口生命周期绑定及监听;提供动态数据源配置支持;提供注解式缓存支持;默认提供 jar 包瘦身方式打包,支持 jar-index 启动。 【免费下载链接】loveqq-framework 项目地址: https://gitcode.com/kfyty725/loveqq-framework

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值