zoukankan      html  css  js  c++  java
  • guavaretrying 加入自定义注解,用aop方式使用

    由于网络环境不太稳定,一些接口方法需要加入重试。正好看到Google's Guava library 项目https://github.com/rholder/guava-retrying,里面功能比较完善。但是官方没有提供注解方式使用,频繁使用会有点麻烦。所以查阅相关资料后编写了支持注解使用的方法

     定义注解类

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * des: guava retrying 注解使用
     * doc: https://github.com/rholder/guava-retrying
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Retry {
        //指定异常时重试  由于pjp.proceed();需要try catch 异常,会有问题暂时没找到解决方法,先注释
    //    Class[] exceptionClass() default {};
    
        //出现Exception时重试
        boolean retryIfException() default false;
    
        //程序出现RuntimeException异常时重试
        boolean retryIfRuntimeException() default false;
    
        //重试次数
        int attemptNumber() default 3;
    
        //重试间隔 ms
        long waitStrategySleepTime() default 1000;
    
        //持续时间; 期间
        long duration() default 0;
    
        //返回值为指定字符串时重试
        String returnResult() default "willRertyString";
    
        //返回值为false时重试(默认关闭)  不支持同时设置指定返回字符串重试
        boolean closeReturnFalseRetry() default true;
    
    
    }
    

     AOP类 

    package net.capitalonline.retry.retryaspect;

    import com.github.rholder.retry.RetryerBuilder;
    import com.github.rholder.retry.StopStrategies;
    import com.github.rholder.retry.WaitStrategies;
    import com.google.common.base.Predicates;
    import net.capitalonline.retry.Retry;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;

    import java.lang.reflect.Method;
    import java.util.concurrent.Callable;
    import java.util.concurrent.TimeUnit;


    /**
    * des: guava retrying 注解使用
    * doc: https://github.com/rholder/guava-retrying
    */


    @Aspect
    @Component
    public class RetryAspect {
    @Pointcut("@annotation(net.capitalonline.retry.Retry)")
    public void MethodCallConstraintPointcut(){
    }

    @Around(value = "@annotation(net.capitalonline.retry.Retry)")
    public Object monitorAround(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("enter retry aspect");
    Method method;
    if (pjp.getSignature() instanceof MethodSignature) { //判断注解是否method 上
    MethodSignature signature = (MethodSignature) pjp.getSignature();
    method = signature.getMethod();
    } else {
    return null;
    }
    Retry annotation = method.getDeclaredAnnotation(Retry.class);
    //重试时间,重试次数
    if (annotation.duration() <= 0 && annotation.attemptNumber() <= 1) {
    return pjp.proceed();
    }

    //不能设置开启returnFalse重试 和指定返回值重试
    if(!annotation.closeReturnFalseRetry() && !annotation.returnResult().equals("willRertyString")){
    return pjp.proceed();
    }

    RetryerBuilder builder = RetryerBuilder.newBuilder();

    //重试次数
    if (annotation.attemptNumber() > 0) {
    builder.withStopStrategy(StopStrategies.stopAfterAttempt(annotation.attemptNumber()));
    }
    //退出策略
    if (annotation.duration() > 0) {
    builder.withStopStrategy(StopStrategies.stopAfterDelay(annotation.duration(), TimeUnit.MILLISECONDS));
    }

    //重试间间隔等待策略
    if (annotation.waitStrategySleepTime() > 0) {
    builder.withWaitStrategy(WaitStrategies.fixedWait(annotation.waitStrategySleepTime(), TimeUnit.MILLISECONDS));
    }

    // //停止重试的策略
    // if (annotation.exceptionClass().length > 0) {
    // for (Class retryThrowable : annotation.exceptionClass()) {
    // if (retryThrowable != null && Throwable.class.isAssignableFrom(retryThrowable)) {
    // builder.retryIfExceptionOfType(retryThrowable);
    // }
    // }
    // }

    //RuntimeException时重试
    if (annotation.retryIfRuntimeException()){
    builder.retryIfRuntimeException();

    }
    if (annotation.retryIfException()){
    builder.retryIfException();
    }
    if (!annotation.returnResult().equals("willRertyString")){
    builder.retryIfResult(Predicates.equalTo(annotation.returnResult()));
    }

    if (!annotation.closeReturnFalseRetry()){
    builder.retryIfResult(Predicates.equalTo(annotation.closeReturnFalseRetry()));
    }

    return builder.build().call(() -> {
    try {
    System.out.println("aspect exec method "+ method.getName());
    return pjp.proceed();
    } catch (Throwable throwable) {
    if (throwable instanceof Exception) {
    throw (Exception) throwable;
    } else {
    throw new Exception(throwable);
    }
    }
    });

    // Callable<Object> callable=new Callable<Object>() {
    // @Override
    // public Object call() throws Exception {
    // try {
    // return pjp.proceed();
    // }catch (Throwable e){
    // e.printStackTrace();
    // System.out.println("测试");
    // return null;
    // }
    // }
    // };
    // try {
    // return builder.build().call(callable);
    // }catch (Exception e){
    // System.out.println("重试");
    // return "error";
    // }
    }
    }

    application.yaml 配置中加入

      aop:
        proxy-target-class: true

     使用实例

    
    
    import org.springframework.stereotype.Component;

    import java.lang.reflect.UndeclaredThrowableException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    @Component
    public class TestA {
    int x=0;
    @Retry(retryIfException = true, waitStrategySleepTime = 1200)
    public void test() throws RemoteException{

    try {
    SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间
    sdf.applyPattern("yyyy-MM-dd HH:mm:ss a");// a为am/pm的标记
    Date date = new Date();// 获取当前时间
    System.out.println("现在时间:" + sdf.format(date)); // 输出已经格式化的现在时间(24小时制)
    int a=1/x;
    System.out.println("1231");
    } catch (Exception e) {
    System.out.println("nonono");
    throw new RemoteException("12321");
    }
    }
    }

      

    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    @WebAppConfiguration
    @ContextConfiguration(classes = Application.class)
    public class Tmpmytest {
        @Autowired
        TestA testA;
        @Test
        public void tmptest() {
            try {
                testA.test();
            } catch (Exception e) {
                System.out.println("ada");
            }
    
    
        }
    
    }
    

      

  • 相关阅读:
    黄聪:手机移动端建站Jquery+CSS3+HTML5触屏滑动特效插件、实现触屏焦点图、图片轮展图
    黄聪:VS2010开发如何在c#中使用Ctrl、Alt、Tab等全局组合快捷键
    利用python实现汉字转拼音
    python 获得质数
    将你的python转成exe格式
    python 动画
    python 饼状图
    python 抓屏
    python 图像迷糊
    python-opencv-圆、椭圆与任意多边形的绘制
  • 原文地址:https://www.cnblogs.com/ytc6/p/15588814.html
Copyright © 2011-2022 走看看