高级JAVA - 手写简单的重试组件学习Spring Retry

目录

一 . 定义注解

二 . 利用cglib代理扩展重试业务

三 . 编写代理类 , 使用自定义的XRetryInterceptor作为拦截器

四 . 编写相关业务方法 , 测试代码

 五 . 测试结果


之前讲了Spring Retry的用法及配置 , 这次通过手写一个简单的组件来学习Spring Retry的实现 . 

源代码 : https://download.csdn.net/download/xingbaozhen1210/11384277

一 . 定义注解

Spring Retry中的@Retryable有很多可设置的属性 , 此处为了便于理解 , 仅设置一个尝试次数

package cn.xing.demo.retry.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @title 重试注解
 * @author Xingbz
 * @createDate 2019-7-18
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface XRetryable {
    int maxAttemps() default 1;//重试次数 , 默认1次
}

二 . 利用cglib代理扩展重试业务

package cn.xing.demo.retry.interceptor;

import cn.xing.demo.retry.annotation.XRetryable;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @title cglib实现重试逻辑
 * @author Xingbz
 * @createDate 2019-7-18
 */
public class XRetryInterceptor implements MethodInterceptor {

    /** 重试次数 */
    private int count;

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        XRetryable retryable = method.getAnnotation(XRetryable.class);//获取方法的XRetryble注解
        if (Objects.isNull(retryable)) {
            return methodProxy.invokeSuper(object, args);//如果没有使用注解则直接执行方法
        }

        /* 有注解的加入异常重试逻辑 */
        int maxAttemps = retryable.maxAttemps();//最大执行次数
        try {
            return methodProxy.invokeSuper(object, args);
        } catch (Throwable e) {
            if (++count == maxAttemps) {
                System.out.println("已达重试次数 :" + maxAttemps + " , 停止重试 . ");
            } else {
                System.out.println("执行[" + method.getName() + "]方法异常 , 准备 第" + (count + 1) + "次执行 . ");
                methodProxy.invoke(object, args);//注意这里不是invokeSuper方法,invokeSuper会退出当前interceptor的处理
            }
        }
        return null;
    }
}

三 . 编写代理类 , 使用自定义的XRetryInterceptor作为拦截器

package cn.xing.demo.retry.proxy;

import cn.xing.demo.retry.interceptor.XRetryInterceptor;
import org.springframework.cglib.proxy.Enhancer;

/**
 * @title 重试代理类 , 使用自定义逻辑作为拦截器
 * @author Xingbz
 * @createDate 2019-7-18
 */
public class XRetryProxy {

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

四 . 编写相关业务方法 , 测试代码

package cn.xing.demo.retry.service;

import cn.xing.demo.retry.annotation.XRetryable;

import java.time.LocalDateTime;

/**
 * @title 使用自定义重试的业务方法
 * @author Xingbz
 * @createDate 2019-7-18
 */
public class XWorkService {

    @XRetryable(maxAttemps = 3)
    public void xwork() {
        System.out.println("执行X方法 : " + LocalDateTime.now());
        throw new RuntimeException();//模拟异常
    }
}
package cn.xing.demo.retry;

import cn.xing.demo.retry.proxy.XRetryProxy;
import cn.xing.demo.retry.service.XWorkService;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @title 自定义重试测试
 * @author Xingbz
 * @createDate 2019-7-18
 */
@SpringBootTest
public class XRetryTest {

    @Test
    public void test() {
        XWorkService service = new XWorkService();
        XRetryProxy proxy = new XRetryProxy();
        XWorkService proxyService = (XWorkService)proxy.xProxyInstance(service);
        proxyService.xwork();
    }
}

 五 . 测试结果

高级JAVA - 手写简单的重试组件学习Spring Retry_第1张图片

你可能感兴趣的:(Java,高级JAVA)