Spring Retry实现原理

来源:互联网 发布:国际淘宝怎么开 编辑:程序博客网 时间:2024/06/04 18:32

在前面这篇博客中介绍了Spring Retry的使用,本文通过一个简单的例子演示Spring Retry的实现原理,例子中定义的注解只包含重试次数属性,实际上Spring Retry中注解可设置属性要多的多,单纯为了讲解原理,所以弄简单点,关于Spring Retry可查阅相关文档、博客。

注解定义

package retry.annotation;import java.lang.annotation.*;/** * Created by Jack.wu on 2016/9/30. */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Retryable {    int maxAttemps() default 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

代理实现

以Cglib作为代理工具,先来写个Callback实现,这也是重试的实现的核心逻辑

package retry.interceptor;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import retry.annotation.Retryable;import java.lang.reflect.Method;/** * Created by Jack.wu on 2016/9/30. */public class AnnotationAwareRetryOperationsInterceptor implements MethodInterceptor{    //记录重试次数    private int times = 0;    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        //获取拦截的方法中的Retryable注解        Retryable retryable = method.getAnnotation(Retryable.class);        if(retryable == null){            return proxy.invokeSuper(obj,args);        }else{ //有Retryable注解,加入异常重试逻辑            int maxAttemps = retryable.maxAttemps();            try {                return proxy.invokeSuper(obj,args);            } catch (Throwable e) {                if(times++ == maxAttemps){                    System.out.println("已达最大重试次数:" + maxAttemps + ",不再重试!");                }else{                    System.out.println("调用" + method.getName() + "方法异常,开始第" + times +"次重试。。。");                    //注意这里不是invokeSuper方法,invokeSuper会退出当前interceptor的处理                    proxy.invoke(obj,args);                }            }        }        return null;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

然后是写个代理类,使用AnnotationAwareRetryOperationsInterceptor作为拦截器

package retry.core;import net.sf.cglib.proxy.Enhancer;import retry.interceptor.AnnotationAwareRetryOperationsInterceptor;/** * Created by Jack.wu on 2016/9/30. */public class SpringRetryProxy {    public Object newProxyInstance(Object target){        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(new AnnotationAwareRetryOperationsInterceptor());        return enhancer.create();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

测试

通过一个用户相关的业务方法来测试上面的代码

接口定义:

package facade;/** * Created by Jack.wu on 2016/9/26. */public interface UserFacade {    void add() throws Exception;    void query() throws Exception;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

接口实现:

package facade.impl;import facade.UserFacade;import retry.annotation.Retryable;/** * Created by Jack.wu on 2016/9/26. */public class UserFacadeImpl implements UserFacade {    @Override    public void add() throws Exception {        System.out.println("添加用户。。。");        throw new RuntimeException();    }    @Override    @Retryable(maxAttemps = 3)    public void query() {        System.out.println("查询用户。。。");        throw new RuntimeException();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

测试:

public class Main {    public static void main(String[] args) throws Exception{        UserFacadeImpl user = new UserFacadeImpl();        //SpringRetry代理测试        SpringRetryProxy springRetryProxy = new SpringRetryProxy();        UserFacade u = (UserFacade)springRetryProxy.newProxyInstance(user);        //u.add();//失败不重试        u.query();//失败重试    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

add方法不添加重试注解,程序异常结束,query方法添加重试注解,设置重试3次,运行效果如下 
这里写图片描述



http://blog.csdn.net/u014513883/article/details/52712870




原创粉丝点击