spring retry重试机制原理解析(手写原理)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

springboot 整合spring retry : https://my.oschina.net/wangjunBlog/blog/1889015

手写spring retry注解

注解实现:

package com.wj.project.api.common.retry.annotation;

import java.lang.annotation.*;
/**
 * @Auther: wangjun
 * @Date: 2018/7/28
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Retryable {

    int maxAttemps() default 0;
}

添加拦截器:

package com.wj.project.api.common.retry.interceptor;

import com.wj.project.api.common.retry.annotation.Retryable;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @Auther: wangjun
 * @Date: 2018/7/28 00:24
 */
public class AnnotationAwareRetryOperationsInterceptor implements MethodInterceptor {

    //记录重试次数
    private int times = 0;

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //获取拦截的方法中的Retryable 注解
        Retryable retryable = method.getAnnotation(Retryable.class);
        if (retryable == null) {
            return methodProxy.invokeSuper(o, objects);
        } else {
            //有Retryable注解
            int maxAttemps = retryable.maxAttemps();
            try {
                return methodProxy.invokeSuper(o, objects);
            } catch (Throwable e) {
                if (times++ == maxAttemps) {
                    System.out.println("已达到最大重试次数:" + maxAttemps + " , 不再重试");
                } else {
                    System.out.println("调用 " + method.getName() + "方法异常,开始第 " + times + "次重试");
                    //注意这里不是 invokeSuper 方法,invokeSuper会退出当前interceptor的处理
                    methodProxy.invoke(o, objects);
                }
            }
        }
        return null;
    }
}

使用cglib动态代理 :

package com.wj.project.api.common.retry.Proxy;

import com.wj.project.api.common.retry.interceptor.AnnotationAwareRetryOperationsInterceptor;
import org.springframework.cglib.proxy.Enhancer;

/**
 * @Auther: wangjun
 * @Date: 2018/7/28 00:39
 */
public class RetryProxy {

    public Object newProxyInstance(Object target){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new AnnotationAwareRetryOperationsInterceptor());
        return enhancer.create();
    }
}

demo测试:

/**
 * @Auther: wangjun
 * @Date: 2018/7/28 00:48
 */
public interface RetryService {
    void testRetry();
}
package com.wj.project.api.attempt.Retry;

import com.wj.project.api.common.retry.annotation.Retryable;

/**
 * @Auther: wangjun
 * @Date: 2018/7/28 00:35
 */
public class RetryServiceImpl implements RetryService{

    private int count = 0;

    @Retryable(maxAttemps = 5)
    public void testRetry() {
        System.out.println("这是第 :" + count + "次执行方法");
        throw new RuntimeException();
    }

}

 

package com.wj.project.api.attempt.Retry;

import com.wj.project.api.common.retry.Proxy.RetryProxy;

/**
 * @Auther: wangjun
 * @Date: 2018/7/28 00:45
 */
public class RetryHandler {

    public static void main(String[] args) {

        RetryServiceImpl retryServiceImpl = new RetryServiceImpl();
        RetryProxy retryProxy = new RetryProxy();
        //创建代理类
        RetryService retryService =(RetryService)retryProxy.newProxyInstance(retryServiceImpl);
        retryService.testRetry();
    }
}

测试结果:

"E:\Program Files\Java\jdk1.8.0_65\bin\java.exe" "-javaagent:E:\Program Files\JetBrains\IntelliJ IDEA 2018.1.6\lib\idea_rt.jar=55570:E:\Program Files\JetBrains\IntelliJ IDEA 2018.1.6\bin" -Dfile.encoding=UTF-8 -classpath "E:\Program Files\Java\jdk1.8.0_65\jre\lib\charsets.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\deploy.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\access-bridge-64.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\cldrdata.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\dnsns.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\jaccess.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\jfxrt.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\localedata.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\nashorn.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\sunec.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\sunjce_provider.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\sunmscapi.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\sunpkcs11.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\ext\zipfs.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\javaws.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\jce.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\jfr.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\jfxswt.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\jsse.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\management-agent.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\plugin.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\resources.jar;E:\Program Files\Java\jdk1.8.0_65\jre\lib\rt.jar;E:\dev\dev-dianrong\wj-springboot-core\wj-api\target\classes;E:\jar\apache-maven-repo2\org\springframework\boot\spring-boot-starter-web\2.0.3.RELEASE\spring-boot-starter-web-2.0.3.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\boot\spring-boot-starter\2.0.3.RELEASE\spring-boot-starter-2.0.3.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\boot\spring-boot\2.0.3.RELEASE\spring-boot-2.0.3.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\boot\spring-boot-autoconfigure\2.0.3.RELEASE\spring-boot-autoconfigure-2.0.3.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\boot\spring-boot-starter-logging\2.0.3.RELEASE\spring-boot-starter-logging-2.0.3.RELEASE.jar;E:\jar\apache-maven-repo2\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;E:\jar\apache-maven-repo2\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;E:\jar\apache-maven-repo2\org\apache\logging\log4j\log4j-to-slf4j\2.10.0\log4j-to-slf4j-2.10.0.jar;E:\jar\apache-maven-repo2\org\apache\logging\log4j\log4j-api\2.10.0\log4j-api-2.10.0.jar;E:\jar\apache-maven-repo2\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;E:\jar\apache-maven-repo2\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;E:\jar\apache-maven-repo2\org\yaml\snakeyaml\1.19\snakeyaml-1.19.jar;E:\jar\apache-maven-repo2\org\springframework\boot\spring-boot-starter-json\2.0.3.RELEASE\spring-boot-starter-json-2.0.3.RELEASE.jar;E:\jar\apache-maven-repo2\com\fasterxml\jackson\core\jackson-databind\2.9.6\jackson-databind-2.9.6.jar;E:\jar\apache-maven-repo2\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;E:\jar\apache-maven-repo2\com\fasterxml\jackson\core\jackson-core\2.9.6\jackson-core-2.9.6.jar;E:\jar\apache-maven-repo2\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.6\jackson-datatype-jdk8-2.9.6.jar;E:\jar\apache-maven-repo2\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.6\jackson-datatype-jsr310-2.9.6.jar;E:\jar\apache-maven-repo2\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.6\jackson-module-parameter-names-2.9.6.jar;E:\jar\apache-maven-repo2\org\springframework\boot\spring-boot-starter-tomcat\2.0.3.RELEASE\spring-boot-starter-tomcat-2.0.3.RELEASE.jar;E:\jar\apache-maven-repo2\org\apache\tomcat\embed\tomcat-embed-core\8.5.31\tomcat-embed-core-8.5.31.jar;E:\jar\apache-maven-repo2\org\apache\tomcat\embed\tomcat-embed-el\8.5.31\tomcat-embed-el-8.5.31.jar;E:\jar\apache-maven-repo2\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.31\tomcat-embed-websocket-8.5.31.jar;E:\jar\apache-maven-repo2\org\hibernate\validator\hibernate-validator\6.0.10.Final\hibernate-validator-6.0.10.Final.jar;E:\jar\apache-maven-repo2\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;E:\jar\apache-maven-repo2\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;E:\jar\apache-maven-repo2\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;E:\jar\apache-maven-repo2\org\springframework\spring-web\5.0.7.RELEASE\spring-web-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\spring-beans\5.0.7.RELEASE\spring-beans-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\spring-webmvc\5.0.7.RELEASE\spring-webmvc-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\spring-aop\5.0.7.RELEASE\spring-aop-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\spring-context\5.0.7.RELEASE\spring-context-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\spring-expression\5.0.7.RELEASE\spring-expression-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\retry\spring-retry\1.2.2.RELEASE\spring-retry-1.2.2.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\spring-core\5.0.7.RELEASE\spring-core-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\springframework\spring-jcl\5.0.7.RELEASE\spring-jcl-5.0.7.RELEASE.jar;E:\jar\apache-maven-repo2\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar" com.wj.project.api.attempt.Retry.RetryHandler
这是第 :0次执行方法
调用 testRetry方法异常,开始第 1次重试
这是第 :0次执行方法
调用 testRetry方法异常,开始第 2次重试
这是第 :0次执行方法
调用 testRetry方法异常,开始第 3次重试
这是第 :0次执行方法
调用 testRetry方法异常,开始第 4次重试
这是第 :0次执行方法
调用 testRetry方法异常,开始第 5次重试
这是第 :0次执行方法
已达到最大重试次数:5 , 不再重试

Process finished with exit code 0

 

 

转载于:https://my.oschina.net/wangjunBlog/blog/1889576

你可能感兴趣的:(spring retry重试机制原理解析(手写原理))