012 spring retry重试原理的解析
有点复杂,在后续的章节,将会对其中涉及到的知识点,再分章节进行说明。
1.程序结构
2.@Retryable
package com.jun.web.annotation.theory; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Retryable { int maxAttemps() default 0; }
3.RetryService
package com.jun.web.annotation.theory; public interface RetryServcie { void testRetry(); }
4.RetryServiceImpl
package com.jun.web.annotation.theory; public class RetryServcieImpl implements RetryServcie { private int count=5; @Override @Retryable(maxAttemps = 5) public void testRetry() { System.out.println("这是第"+count+"执行方法"); throw new RuntimeException(); } }
5.拦截器
MethodInterceptor接口被用来拦截指定的方法,对方法进行增强
具体的是哪个方法,将会通过Enhancer说明
package com.jun.web.annotation.theory; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; //MethodInterceptor接口被用来拦截指定的方法,对方法进行增强 public class AnnotationRetryInterceptor implements MethodInterceptor { private int times=0; @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //obj是代理后的子类 ,method是调用方法 ,args是方法入参 , proxy是MethodProxy代理对象 //获取拦截方法中的注解 Retryable retryable = method.getAnnotation(Retryable.class); if(retryable==null){ return methodProxy.invokeSuper(o, objects); }else{ int maxAttemps = retryable.maxAttemps(); try { return methodProxy.invokeSuper(o,objects); }catch (Throwable t){ if (times++ == maxAttemps){ System.out.println("已经达到最大值:"+times); }else { System.out.println("调用"+method.getName()+"方法异常,开始第"+times+"次重试"); methodProxy.invoke(o,objects); } } } return null; } }
6.代理
package com.jun.web.annotation.theory; import org.springframework.cglib.proxy.Enhancer; public class RetryProxy { public Object newProxyInstance(Object target){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new AnnotationRetryInterceptor()); return enhancer.create(); } }
7.测试
package com.jun.web.annotation.theory; public class RetryHandler { public static void main(String[] args) { RetryServcieImpl retryServcieImpl = new RetryServcieImpl(); RetryProxy retryProxy = new RetryProxy(); // RetryServcie retryServcie = (RetryServcie) retryProxy.newProxyInstance(retryServcieImpl); retryServcie.testRetry(); } }
8.效果
Connected to the target VM, address: '127.0.0.1:59161', transport: 'socket' 这是第5执行方法 调用testRetry方法异常,开始第1次重试 这是第5执行方法 调用testRetry方法异常,开始第2次重试 这是第5执行方法 调用testRetry方法异常,开始第3次重试 这是第5执行方法 调用testRetry方法异常,开始第4次重试 这是第5执行方法 调用testRetry方法异常,开始第5次重试 这是第5执行方法 已经达到最大值:6 Disconnected from the target VM, address: '127.0.0.1:59161', transport: 'socket'