Aop 切面 Feign 记录

5,024 阅读3分钟

1、Aop 切面 Feign 记录

/**
 * @author xpy
 * @desc
 * @date 2019/9/6 10:17
 */
@Component
@Scope("prototype")
@Aspect
public class FeignLogAop {
    private Logger logger= LoggerFactory.getLogger(getClass());
    @Resource
    private InterfaceDataRecordMapper interfaceDataRecordMapper;
    private InterfaceDataRecordWithBLOBs recordWithBLOBs;

    /**
     * 功能描述: 定义切点切人feign.client包下所有类
     * @Return: void
     * @Author: XPY
     * @Date: 2019/9/6 11:25
     */
    @Pointcut("execution(* com.yiyu.feign.client..*.*(..)) ")
    public void executeService(){}
    /**
     * 功能描述: 方法执行前切入
     * @Param: [joinPoint]
     * @Return: void
     * @Author: XPY
     * @Date: 2019/9/6 11:26
     */
    @Before(value = "executeService()")
    public void beforeAdvice(JoinPoint joinPoint){
        try {
            if(this.recordWithBLOBs == null){
                this.recordWithBLOBs = new InterfaceDataRecordWithBLOBs();
            }
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            PostMapping postMapping = method.getAnnotation(PostMapping.class);
            GetMapping getMapping = method.getAnnotation(GetMapping.class);
            RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
            if(postMapping == null && getMapping == null && requestMapping == null){
                return;
            }
            String[] value = new String[]{};
            if(postMapping != null){
                value = postMapping.value();
            }
            if(getMapping != null){
                value = getMapping.value();
            }
            if(requestMapping != null){
                value = requestMapping.value();
            }
            if(value.length <= 0){
                return;
            }
            Object[] args = joinPoint.getArgs();
            this.recordWithBLOBs.setInterfaceUrl(value[0]);
            this.recordWithBLOBs.setInterfaceDataRecordId(GenerateCode.randomUUID());
            this.recordWithBLOBs.setInterfaceParam(JSONObject.toJSONString(args));
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
        }
    }
    /**
     * 功能描述: 方法执行返回值时
     * @Param: [obj]
     * @Return: void
     * @Author: XPY
     * @Date: 2019/9/6 11:26
     */
    @AfterReturning(value = "executeService()" , returning="obj")
    public void afterAdviceReturn(Object obj){
        try {
            if(obj != null){
                JSONObject jsonObject = JSON.parseObject((String)obj);
                Integer status = jsonObject.getInteger("Code")!=null?jsonObject.getInteger("Code"):jsonObject.getInteger("status");
                this.recordWithBLOBs.setInterfaceFlag(status);
                this.recordWithBLOBs.setInterfaceResult(JSONObject.toJSONString(obj));
                interfaceDataRecordMapper.insert(this.recordWithBLOBs);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
        }
    }
}

Pointcut

匹配包

  • 匹配ProductService类里头的所有方法 @Pointcut("within(com.zhb.service.ProductService)")

  • 匹配com.zhb包及子包下所有类的方法 @Pointcut("within(com.zhb..*)")

匹配对象

  • 匹配AOP对象的目标对象为指定类型的方法,即LogService的aop代理对象的方法 @Pointcut("this(com.zhb.log.Loggable)")

  • 匹配实现Loggable接口的目标对象(而不是aop代理后的对象)的方法 @Pointcut("target(com.zhb.log.Loggable)")

匹配所有以Service结尾的bean里头的方法 @Pointcut("bean(*Service)")

匹配参数 args()

  • 匹配任何以find开头而且只有一个Long参数的方法 @Pointcut("execution(* ..find(Long))")

  • 匹配任何以find开头的而且第一个参数为Long型的方法 @Pointcut("execution(* ..find(Long,..))")

  • 匹配任何只有一个Long参数的方法 @Pointcut("within(com.zhb..*) && args(Long)")

  • 匹配第一个参数为Long型的方法 @Pointcut("within(com.zhb..*) && args(Long,..)")

匹配注解

  • 匹配方法标注有AdminOnly的注解的方法 @Pointcut("@annotation(com.zhb.anno.AdminOnly) && within(com.zhb..*)")

  • 匹配标注有NeedSecured的类底下的方法 //class级别 @Pointcut("@within(com.zhb.anno.NeedSecured) && within(com.zhb..*)")

  • 匹配标注有NeedSecured的类及其子类的方法 //runtime级别

  • 在spring context的环境下,二者没有区别 @Pointcut("@target(com.zhb.anno.NeedSecured) && within(com.zhb..*)")

  • 匹配传入的参数类标注有Repository注解的方法 @Pointcut("@args(com.zhb.anno.NeedSecured) && within(com.zhb..*)")

匹配方法

  • 匹配任何公共方法 @Pointcut("execution(public * com.zhb.service..(..))")

  • 匹配com.zhb包及子包下Service类中无参方法 @Pointcut("execution(* com.zhb..Service.())")

  • 匹配com.zhb包及子包下Service类中的任何只有一个参数的方法 @Pointcut("execution(* com.zhb..Service.(*))")

  • 匹配com.zhb包及子包下任何类的任何方法 @Pointcut("execution(* com.zhb...(..))")

  • 匹配com.zhb包及子包下返回值为String的任何方法 @Pointcut("execution(String com.zhb...(..))")

  • 匹配异常 execution(public * com.zhb.service..(..) throws java.lang.IllegalAccessException)

通知类型

  • Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可

  • AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值

  • AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象

  • After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式

  • Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint