aop

远程的 aop 调用,有时候需要 aop 的统一拦截。

方法返回值

一般的 rpc 调用都会有统一的参数,比如 respCode, respMessage。

V1-统一父类 BaseResp-错误

@Around("@annotation(MyAop)")
public Object aop(ProceedingJoinPoint joinPoint,
                        MyAop myAop) throws Throwable {
    Object returnObj = null;
    try {
        // 记录请求的入参等

        returnObj = joinPoint.proceed();
        return returnObj;
    } catch (BizException e) {
        return returnObj;
    } catch (NetTimeoutException e){
        log.error("服务超时", e);
        return returnObj;
    } catch (Throwable e) {
        log.error("调用异常", e);
        return returnObj;
    } finally {
        // 最后的逻辑处理
    }
}

当出现异常的时候,我们容易想到统一处理 returnObj 为:

BaseResp resp = new BaseResp();
resp.setRespCode("xxx");
resp.setRespDesc("yyy");

但是对于返回值,如果使用 BaseResp,会导致强转失败。

V2-基于反射-异常丢失

第二种比较常见的方式,是基于反射。

比如一个公司内,所有的响应编码如果是统一的话:

Class<?> returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
// 如果原始返回 void
if(returnType == void.class) {
    return null;
}

Object returnObj = returnType.newInstance();
BeanUtils.setProperty(returnObj, LensConstants.RESP_CODE, respCode);
BeanUtils.setProperty(returnObj, LensConstants.RESP_DESC, respMessage);
return returnObj;

这里考虑了 void 类型的。

不过这个会有一定的问题,如果我们在方法中定义了异常抛出,会导致方法中业务异常被捕获。

所以结合个人情况,我不建议这么做。

v3-抛出异常

我们作为调用者,直接抛出异常。如果作为服务端,可以考虑统一捕获异常。

/**
     * 创建对象
     * @param joinPoint 切面
     * @param respCode 响应编码
     * @param respMessage 响应消息
     * @return 结果
     * @throws Throwable 异常
     * @since 224
     */
    private Object createResp(final ProceedingJoinPoint joinPoint,
                            String respCode,
                            String respMessage) throws Throwable{
//        Class<?> returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
//        // 如果原始返回 void
//        if(returnType == void.class) {
//            return null;
//        }
//
//        Object returnObj = returnType.newInstance();
//        BeanUtils.setProperty(returnObj, LensConstants.RESP_CODE, respCode);
//        BeanUtils.setProperty(returnObj, LensConstants.RESP_DESC, respMessage);
//        return returnObj;
        // 避免方法中异常被捕获
        throw new BizException(respCode, respMessage);
    }

参考资料