package com.fenbi.ep.ehr.server.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Retryable {
/**
* 捕获的异常
*/
Class<? extends Throwable> catchException() default RuntimeException.class;
/**
* 最大重试次数(包含第一次调用)。即maxAttempts=1则不进行重试。默认重试两次
*/
int maxAttempts() default 3;
/**
* 默认重试间隔。重试时间为重试间隔*(重试次数-1)
* @return
*/
long waitTime() default 5000;
}
package com.fenbi.ep.ehr.server.aspect;
import com.fenbi.ep.ehr.server.annotation.Retryable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
/**
* 注意:方法幂等要求
*/
public class RetryAspect {
protected final Logger LOG = LoggerFactory.getLogger(getClass());
@Pointcut("@annotation(com.fenbi.ep.ehr.server.annotation.Retryable)")
public void myPointcut() {
}
@Around("myPointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
Method method = getCurrentMethod(point);
Retryable retryable = method.getAnnotation(Retryable.class);
int maxAttempts = retryable.maxAttempts();
int times = 0;
final Class<? extends Throwable> exceptionClass = retryable.catchException();
while (times < maxAttempts) {
try {
return point.proceed();
} catch (Throwable e) {
times++;
Thread.sleep(retryable.waitTime()*(times-1));
// 超过最大重试次数 or 不属于当前处理异常
if (times >= maxAttempts ||
!exceptionClass.isAssignableFrom(e.getClass())) {
throw e;
}
LOG.error("{}方法调用异常,方法运行次数:{}",method.getName(), times, e);
}
}
return null;
}
private Method getCurrentMethod(ProceedingJoinPoint point) {
try {
Signature sig = point.getSignature();
MethodSignature msig = (MethodSignature) sig;
Object target = point.getTarget();
return target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}
参考链接:https://www.jianshu.com/p/2e3cfc509d56