In the previous blog, we introduced the use of Spring Retry. This article demonstrates the implementation principle of Spring Retry through a simple example. The annotations defined in the example only contain the number of retry attributes. In fact, the annotations in Spring Retry can set more attributes. In order to explain the principle, it is simpler. For Spring Retry, you can check relevant documents and blogs.
Annotation definition
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;}Agent implementation
Using Cglib as a proxy tool, first write a Callback implementation, which is also the core logic of the retry implementation.
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{ //Record the number of retries private int times = 0; @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { //Get Retryable annotation in the intercepted method Retryable retryable = method.getAnnotation(Retryable.class); if(retryable == null){ return proxy.invokeSuper(obj,args); }else{ //With Retryable annotation, add exception retry logic int maxAttemps = retryable.maxAttemps(); try { return proxy.invokeSuper(obj,args); } catch (Throwable e) { if(times++ == maxAttemps){ System.out.println("Maximum retries have been reached: " + maxAttemps + ", no more retry!"); }else{ System.out.println("Call" + method.getName() + "Method exception, start "+ times +" retry... "); //Note that this is not the invokeSuper method, invokeSuper will exit the current interceptor processing proxy.invoke(obj,args); } } } return null; }}Then write a proxy class and use AnnotationAwareRetryOperationsInterceptor as an interceptor
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(); }}test
Test the above code through a user-related business method
Interface definition:
package facade;/** * Created by Jack.wu on 2016/9/26. */public interface UserFacade { void add() throws Exception; void query() throws Exception;}Interface implementation: 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("Add user..."); throw new RuntimeException(); } @Override @Retryable(maxAttemps = 3) public void query() { System.out.println("Query user..."); throw new RuntimeException(); }}test:
public class Main { public static void main(String[] args) throws Exception{ UserFacadeImpl user = new UserFacadeImpl(); //SpringRetry proxy test SpringRetryProxy springRetryProxy = new SpringRetryProxy(); UserFacade u = (UserFacade)springRetryProxy.newProxyInstance(user); //u.add();//No retry u.query();//Failed retry }} The add method does not add retry annotations, the program ends abnormally, the query method adds retry annotations, sets retry 3 times, and the running effect is as follows
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.