zoukankan      html  css  js  c++  java
  • 自定义注解-方法重试@RetryProcess

    背景

    在项目开发中,有时候会出现接口调用失败,本身调用又是异步的,如果是因为一些网络问题请求超时,总想可以重试几次把任务处理掉。
    一些RPC框架,比如dubbo都是有重试机制的,但是并不是每一个项目多会使用dubbo框架,常规的小项目有时候直接使用http进行不同项目之间的交互。

    思路

    使用spring aop和自定义注解来,建立一套重试机制。
    根据切入点和自定义注解,来完成重试工作。

    自定义注解

    定义注解

    package com.github.feifuzeng.study.annotation;
    
    import org.springframework.stereotype.Component;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @author feifz
     * @version 1.0.0
     * @Description 重试机制自定义注解
     * @createTime 2019年06月20日 14:05:00
     */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface RetryProcess {
        int value() default 1;
    
        int sleep() default 1000;
    }
    

    注解中value参数为重试次数,默认为1,sleep为重试间隔,默认为1000毫秒。

    定义切面

    package com.github.feifuzeng.study.annotation;
    
    /**
     * @author feifz
     * @version 1.0.0
     * @Description 重试注解切面
     * @createTime 2019年06月20日 14:07:00
     */
    
    import lombok.extern.log4j.Log4j2;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
    import org.springframework.stereotype.Component;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    @Aspect
    @Component
    @Log4j2
    public class RetryProcessAspect {
        private AtomicInteger atomicInteger = new AtomicInteger(0);
    
        @AfterThrowing(pointcut=("@annotation(com.github.feifuzeng.study.annotation.RetryProcess)"))
        public void tryAgain(JoinPoint point) {
            try {
                MethodSignature methodSignature = (MethodSignature) point.getSignature();
                RetryProcess retryProcess = methodSignature.getMethod().getAnnotation(RetryProcess.class);
    
                if (atomicInteger.intValue() < retryProcess.value()) {
                    int i = atomicInteger.incrementAndGet();
                    Thread.sleep(retryProcess.sleep() * i);
                    log.debug("开始重试第" + i + "次");
                    MethodInvocationProceedingJoinPoint methodPoint = ((MethodInvocationProceedingJoinPoint) point);
                    methodPoint.proceed();
                }
            } catch (Throwable throwable) {
                tryAgain(point);
            }
        }
    }
    
    

    使用示例

    @RetryProcess(value = 2,sleep = 2000)
        public List<User> findList() {
            return userMapper.queryUserList();
        }
    

    该自定义注解用于方法上,当改方法在执行过程中存在异常,不管是系统异常还是手动抛出的业务异常,均可实现重试。

    知识课堂

    JoinPoint 对象

    JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
    常用api:

    方法名 功能
    Signature getSignature(); 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
    Object[] getArgs(); 获取传入目标方法的参数对象
    Object getTarget(); 获取被代理的对象
    Object getThis(); 获取代理对象

    ProceedingJoinPoint对象

    ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中,
    添加了

    Object proceed() throws Throwable //执行目标方法
    Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法

    两个方法.
    MethodInvocationProceedingJoinPoint 对象

    查看源码得知MethodInvocationProceedingJoinPoint是ProceedingJoinPoint和StaticPart的实现,只要使用的还是ProceedingJoinPoint对象的两个实现方法。

    参考

    结语

    欢迎关注微信公众号『码仔zonE』,专注于分享Java、云计算相关内容,包括SpringBoot、SpringCloud、微服务、Docker、Kubernetes、Python等领域相关技术干货,期待与您相遇!

  • 相关阅读:
    函数指针Demo
    设计模式笔记
    Simple Factory 模式
    百度API操作实例
    如何发邮件不被认定为垃圾邮件的技巧
    DateTimePicker中自定义时间或日期显示格式
    取得指定月份的天数
    DataGridView中的内容太长时换行显示
    Numericupdown控件value值的非空判断
    C#中用SQL语句CreatTable
  • 原文地址:https://www.cnblogs.com/feifuzeng/p/13626485.html
Copyright © 2011-2022 走看看