spring aop 统一进行日常及异常的处理

  • AOP就是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP使得业务逻辑各个部分的耦合度降低,提高程序的可重用性。
  • 为什么使用AOP?
    我们写的代码难免有些运行错误,通常情况下,我们需要对错误进行包装,不能直接返回异常信息发给前端。
    但是我们的前端很容易臃肿,就像我在公司里面写的一样
 @GetMapping(value = "kmp")
  public BaseResponse kmp(@RequestParam String big, @RequestParam String small) {
    logger.info("kmp request,big=%s,small=%s", big, small);
    BaseResponse baseResponse = new BaseResponse();
    try {
      baseResponse.result = analyticsService.stringIndex(big, small);
    } catch (Exception e) {
      logger.info("kmp error,error=%s", e);
      return new BaseResponse(BaseError.FAIL);
    }
    logger.info("kmp response,result=%s", baseResponse);
    return baseResponse;
  }

这些代码看起来就是很臃肿,发现里面处理很多错误信息,但是其实只是执行了一种方法:

baseResponse.result = analyticsService.stringIndex(big, small);

看起来有点大费周章了。

  • 接下来我们可以使用AOP来解决这种问题
    (1)环境配置
    在pom.xml中添加依赖的包
<dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjweaver</artifactId>
     <version>1.8.13</version>
</dependency>

(2)如何使用AOP
我们改造上面的方法:

@GetMapping(value = "kmp")
public Object kmp(@RequestParam String big, @RequestParam String small) {
  return analyticsService.stringIndex(big, small);
}

改造成只是简单的调用方法,然后直接返回。
那么问题来了,我们日志呢?我们的异常处理呢?
我们可以在切面里做处理

@Aspect
@Component
public class ExceptionAspect {

  private Logger logger = LoggerFactory.getLogger(this.getClass());

  /**
   * 在方法调用之前,打印入参
   */
  @Before(value = "execution(public * com.huyan.demo.controller.AnalyticsController.*(..))")
  public void before(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getName();
    String methodName = joinPoint.getSignature().getName();
    Object[] args = joinPoint.getArgs();
    StringBuilder params = new StringBuilder();
    for (Object arg : args) {
      params.append(arg).append(" ");
    }
    logger.info(className + "的" + methodName + "入参为:" + params.toString());
  }

  /**
   * 过程中监测,catch到异常之后返回包装后的错误信息,并打印日志
   */
  @Around(value = "execution(public * com.huyan.demo.controller.AnalyticsController.*(..))")
  public BaseResponse catchException(ProceedingJoinPoint joinPoint) {
    try {
      BaseResponse baseResponse = new BaseResponse(BaseError.SUCCESS);
      baseResponse.result = joinPoint.proceed();
      return baseResponse;
    } catch (Throwable e) {
      String className = joinPoint.getTarget().getClass().getName();
      String methodName = joinPoint.getSignature().getName();
      logger.warn("在" + className + "的" + methodName + "中,发生了异常:" + e);
      return new BaseResponse(BaseError.FAIL);
    }
  }

  /**
   * 返回之后,打印出参
   */
  @AfterReturning(value = "execution(public * com.huyan.demo.controller.AnalyticsController.*(..))", returning = "returnVal")
  public void afterReturin(JoinPoint joinPoint, Object returnVal) {
    String className = joinPoint.getTarget().getClass().getName();
    String methodName = joinPoint.getSignature().getName();
    logger.info(className + "的" + methodName + "结果为:" + returnVal.toString());
  }
}

看到上面的信息可以看到注解里面的值就是我们这个切面覆盖的范围。使用execution表达式来定义切点。

(3)AOP优势
看到这个切面类,我们可以清晰的看到,这个方法异常处理类统一放到异常处理类中,极大的减少了代码量。使得业务层业务逻辑看起来更加清晰。

(4)AOP的其他应用场景
性能监控,访问统计以及权限验证也是AOP经典场景

发现注解里面可以我们执行这个处理的文件范围,也可以是我们我自己定义的注解,然后让这个注解去放在方法上,让这个处理生效。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值