com.kqinfo.universal.retry.aspect.RetryAspect Maven / Gradle / Ivy
package com.kqinfo.universal.retry.aspect;
import com.alibaba.fastjson.JSON;
import com.kqinfo.universal.retry.annotation.Retry;
import com.kqinfo.universal.retry.constant.StatusEnum;
import com.kqinfo.universal.retry.context.RetryContext;
import com.kqinfo.universal.retry.domain.RetryRecord;
import com.kqinfo.universal.retry.service.RetryRecordService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import javax.annotation.Resource;
import java.beans.Introspector;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
/**
* @author Zijian Liao
* @since 1.0.0
*/
@Slf4j
@Aspect
public class RetryAspect {
@Resource
private RetryRecordService retryRecordService;
@Around(value = "@annotation(retry)")
public Object around(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
try {
return joinPoint.proceed();
} catch (Throwable e) {
// 如果是重试调用,直接抛出异常
if(RetryContext.isRetry()){
throw e;
}
// 如果是需要重试的异常并且不在忽略的异常中
if (isRetryEx(retry, e) && !isNoRetryEx(retry, e)) {
// 记录重试
saveRetryRecord(joinPoint, retry, e);
}else {
// 其他情况将异常抛出
throw e;
}
}
return null;
}
private boolean isRetryEx(Retry retry, Throwable e) {
// 如果没有配置,则表示任何异常都要重试
if (retry.retryFor().length == 0) {
return true;
}
for (Class extends Throwable> retryClass : retry.retryFor()) {
if (match(e.getClass(), retryClass.getName())) {
return true;
}
}
return false;
}
private boolean isNoRetryEx(Retry retry, Throwable e) {
for (Class extends Throwable> noRetryClass : retry.noRetryFor()) {
if (match(e.getClass(), noRetryClass.getName())) {
return true;
}
}
return false;
}
private void saveRetryRecord(ProceedingJoinPoint joinPoint, Retry retry, Throwable e) throws InvocationTargetException, IllegalAccessException {
// 取出类名,方法名,参数列表
Class> targetClass = joinPoint.getTarget().getClass();
final String beanName = Introspector.decapitalize(targetClass.getSimpleName());
// 方法名
final Method method = resolveMethod(joinPoint);
// 参数列表
final Object[] args = joinPoint.getArgs();
final List