方式1

依赖

不加人这个依赖不会生效,代码也不报错,坑死

springboot 2.7.4

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1
extends AbstractPointcutAdvisor
1
2
3
4
5
6
7
8
9
10
11
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(RetryRegistrarConfiguration.class)
//@Import(RetryImportSelectorRegistrar.class)
public @interface EnableRetry {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)
public @interface Retry {

/**
* 重试次数
*
* @return
*/
int times() default 0;

/**
* 遇到异常是否抛出
*
* @return
*/
boolean isThrow() default false;

}

extends AbstractPointcutAdvisor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class RetryAnnotationAdvisor extends AbstractPointcutAdvisor
implements BeanFactoryAware {

private Advice advice;

private Pointcut pointcut;

public RetryAnnotationAdvisor() {
advice = new RetryInterceptor();
pointcut = new RetryPointcut();
}

@Override
public Pointcut getPointcut() {
return pointcut;
}

@Override
public Advice getAdvice() {
return advice;
}

@Override
public void setBeanFactory(BeanFactory beanFactory) {
if (this.advice instanceof BeanFactoryAware) {
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

@Slf4j
public class RetryInterceptor implements MethodInterceptor {

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("RetryInterceptor");
Retry retry = invocation.getMethod()
.getDeclaredAnnotation(Retry.class);
if (retry != null) {
int times = retry.times();
boolean isThrow = retry.isThrow();
if (times > 0) {
for (int i = 0; i < times; i++) {
try {
System.out.println("调用"+(i+1));
return invocation.proceed();
} catch (Exception e) {
log.error("invoke retry error.");
if (i == times - 1 && isThrow) {
throw e;
}
}
}
}
}
return invocation.proceed();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.annotation.AnnotationMethodMatcher;

public class RetryPointcut implements Pointcut {

@Override
public ClassFilter getClassFilter() {
return ClassFilter.TRUE;
}

@Override
public MethodMatcher getMethodMatcher() {
return new AnnotationMethodMatcher(Retry.class, true);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.springframework.context.annotation.Bean;

public class RetryRegistrarConfiguration {

@Bean
public RetryAnnotationAdvisor retryAnnotationAdvisor() {
System.out.println("===========================");
System.out.println("===========================");
System.out.println("==============RetryAnnotationAdvisor=============");
System.out.println("===========================");
System.out.println("===========================");
return new RetryAnnotationAdvisor();
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Service
public class XXXService {

@Retry(times = 3)
public void testRetry(Integer a) {
// 执行方法
System.out.println(LocalDateTime.now());
System.out.println(1/a);

}
}

controller调用即可

方式2

不加aop依赖也行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor;
import org.springframework.beans.factory.BeanFactory;

public class RetryAdvisingBeanPostProcessor
extends AbstractBeanFactoryAwareAdvisingPostProcessor {
@Override
public void setBeanFactory(BeanFactory beanFactory) {
// 这里重写setBeanFactory一是为了兼容advisor需要使用bean工厂对象情况
// 二是将RetryAnnotationAdvisor赋值给advisor对象,如果不需要设置bean
// 工厂到Advisor中,那么实现InitializingBean接口,在afterPropertiesSet
// 方法中把RetryAnnotationAdvisor赋值给advisor对象也可以
super.setBeanFactory(beanFactory);

RetryAnnotationAdvisor advisor = new RetryAnnotationAdvisor();
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class RetryImportSelectorRegistrar implements ImportSelector {

private static final String[] IMPORTS = new String[] {
RetryAdvisingBeanPostProcessor.class.getName()};

@Override
public String[] selectImports(
AnnotationMetadata importingClassMetadata) {
return IMPORTS;
}
}