aop 注解记录接口调用日志

原创
2019/01/08 22:31
阅读数 788

一、定义注解

package com.github.dgw.annotation;

import com.github.dgw.enums.InterfaceType;

import java.lang.annotation.*;

/**
 * 封装远程调用api 注解
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InvokeInterfaceLog {

    //请求url
    String requestUrl() default "";

    //入参字段
    String[] params() default {};

    //回参字段
    String[] result() default {};

    //方法名称
    String methodName() default "";

    //业务关联唯一id
    String uniqueId() default "";

    //接口类型
    InterfaceType interfaceType() default InterfaceType.TEST_INTERFACE_TYPE;

}

二、定义解析类

package com.github.dgw.config;

import com.github.dgw.annotation.InvokeInterfaceLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class InvokeInterfaceLogAspect {

    private final static Logger logger= LoggerFactory.getLogger(InvokeInterfaceLogAspect.class);

    //只切带RedisLock注解的方法
    @Pointcut("@annotation(com.github.dgw.annotation.InvokeInterfaceLog)")
    public void executeService(){

    }

    /**
     * 环绕通知
     * @return
     * @throws Throwable
     */
    @Around("executeService()")
    public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        //1,获取方法参数,作为redis存储时的key
//        Map<String, Object> methodParam = getMethodParam(proceedingJoinPoint);
        return proceedingJoinPoint.proceed();
    }

    /**
     * 后置通知,方法调用后被调用(取不到返回值)
     */
    @After("executeService()")
    public void doAfterAdvice(JoinPoint joinPoint){
//        Map<String, Object> methodParam = getMethodParam(joinPoint);
//        System.out.println(methodParam);
    }

    /**
     * 后置返回通知
     */
    @AfterReturning(pointcut="executeService()",returning="result")
    public void doAfterReturningAdvice(JoinPoint joinPoint,Object result){
        Map<String, Object> methodParam = getMethodParam(joinPoint);
        String[] params = (String[]) methodParam.get("params");
        Map<String,Object> p=new HashMap<>();
        Object[] args = joinPoint.getArgs();

        System.out.println(methodParam.get("requestUrl"));
        System.out.println(methodParam.get("params"));
        System.out.println(methodParam.get("result"));
        System.out.println(methodParam.get("methodName"));
        System.out.println(methodParam.get("uniqueId"));
        System.out.println(methodParam.get("interfaceType"));


    }


    //获取注解方法参数
    private  Map<String, Object> getMethodParam(JoinPoint joinPoint){

        Class target = joinPoint.getTarget().getClass();
        Method[] methods = target.getMethods();
        String methodName = joinPoint.getSignature().getName();

        for(Method method:methods){
            if(method.getName().equals(methodName)){
                Map<String, Object> result = new HashMap<String, Object>();
                InvokeInterfaceLog annotation = method.getAnnotation(InvokeInterfaceLog.class);
                String uniqueId = parseKey(annotation.uniqueId(), method, joinPoint.getArgs());
                result.put("requestUrl", annotation.requestUrl());
                result.put("params", annotation.params());
                result.put("result", annotation.result());
                result.put("methodName", annotation.methodName().equals("")?methodName:annotation.methodName());
                result.put("uniqueId", uniqueId);
                result.put("interfaceType", annotation.interfaceType());
                return result;
            }
        }
        return null;
    }

    /**
     *    获取缓存的key
     *    key 定义在注解上,支持SPEL表达式
     * @param
     * @return
     */
    private String parseKey(String key,Method method,Object [] args){

        //获取被拦截方法参数名列表(使用Spring支持类库)
        LocalVariableTableParameterNameDiscoverer u =new LocalVariableTableParameterNameDiscoverer();
        String [] paraNameArr=u.getParameterNames(method);

        //使用SPEL进行key的解析
        ExpressionParser parser = new SpelExpressionParser();
        //SPEL上下文
        StandardEvaluationContext context = new StandardEvaluationContext();
        //把方法参数放入SPEL上下文中
        for(int i=0;i<paraNameArr.length;i++){
            context.setVariable(paraNameArr[i], args[i]);
        }
        return parser.parseExpression(key).getValue(context,String.class);
    }

}

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部