这个链接是实例:https://blog.csdn.net/weixin_41381863/article/details/89856440
对注解讲解的比较全;


在项目开发中,经常会遇到需要重试的地方。除了自己写循环(不是那么优雅,也不方便维护,关键是可能还不那么可靠)重试之外,还可以使用spring retry。
spring retry主要实现了重试和熔断。
不适合重试的场景:
参数校验不合法、写操作等(要考虑写是否幂等)都不适合重试。
适合重试的场景:
远程调用超时、网络突然中断等可以重试。
在spring retry中可以指定需要重试的异常类型,并设置每次重试的间隔以及如果重试失败是继续重试还是熔断(停止重试)。

1 快速开始

1、在项目中引入jar包:

  1. <dependency>
  2. <groupId>org.springframework.retry</groupId>
  3. <artifactId>spring-retry</artifactId>
  4. </dependency>
  5. <!--还需要aspectjweaver依赖-->
  6. <dependency>
  7. <groupId>org.aspectj</groupId>
  8. <artifactId>aspectjweaver</artifactId>
  9. </dependency>

2、将目标类配置为spring的bean,并在配置中加入启动重试功能注解:@EnableRetry(如果是springboot项目,在启动类上添加该注解也可)

@Configuration
@EnableRetry
public class Config

或者

@SpringBootApplication
@EnableRetry
public class Application

3、在需要重试的相关类的方法中加上@Retryable即可实现重试。

@Retryable(Exception.class)
@Override
public String targetMethod() throws Exception

2 注意事项

1、由于retry用到了aspect增强,所以在方法内部调用,会使aspect增强失效,那么retry当然也会失效。
示例:

public class RetryService {


    public void method1() {
        method2();//内部调用retry会失效
    }

    @Retryable(Exception.class)
    public void method2() {
        throw new RuntimeException("这里出现异常,该方法需要重试....");
    }
}

2、很多地方都说不能在接口的实现类上使用这个注解,是错误的,目标方法不能有返回值,也是错误的,亲测有效哈(下面的demo就以在接口的实现类中使用@Retryable进行展示),当然也可以自行去写demo试一试。
我引进来之后的版本是
12 spring-retry重试框架  重试机制 - 图1

其它版本自行测试一遍。
3、被重试的目标方法所在的类必须配置为spring的bean
4、spring retry的重试机制是同步进行的,不是异步

3 简单的示例

1、重试目标(接口和实现类(可以映射为生成环境的service层))

--接口
public interface IRetryService {

    String targetMethod() throws Exception;
}

--实现类
@Component
public class RetryServiceImpl implements IRetryService {

    @Retryable(Exception.class)
    @Override
    public String targetMethod() throws Exception {
        System.out.println("目标被调用");
        Random random = new Random();
        int i = random.nextInt(10);
        if (i > 1) {
            throw new NullPointerException("大于1");
        }
        return "小于或等于1";
    }
}

2、配置类(一定要将重试目标交给IoC管理)

@Configuration
@EnableRetry//开启重试功能,springboot项目可作用于启动类上
public class RetryConfig {

    @Bean(name="retryServiceImpl")
    public RetryServiceImpl initRetryService() {
        return new RetryServiceImpl();
    }
}

3、测试类及结果

@RunWith(SpringRunner.class)
@SpringBootTest
public class RetryServiceTest {

    @Autowired
    private IRetryService iRetryService;

    @Test
    public void methodA() {
        try {
            String result = iRetryService.targetMethod();
            System.out.println("test-->" + result);
        } catch (Exception e) {
            System.out.println("目标方法异常....");
        }
    }
}

----------------------------------------------------------------------

目标被调用
目标被调用
目标被调用
test-->小于或等于1

说明
可以明显的看到,目标方法被重试了3次(多次运行测试类结果不一定相同的,但是一旦目标方法产生指定的异常,则进行重试,有可能重试之后,得到了一个异常,但是,不管怎么运行测试方法,最多只重试了3次)。

4 @Retryable注解和@Recover注解常用属性详解

1 @Recover注解

—>value属性:Throwable子类的Class数组,指定发生具体的异常进行重试,默认是所有异常都重试;
—>include属性:同value属性;
—>exclude属性:指定不处理的异常,Throwable子类的Class数组;
—>maxAttemps:最大尝试次数(包括第一次失败)默认为3次;
—>backoff:重试补偿机制,默认没有

2 @Backoff注解

—>delay:指定延迟后重试,默认为1000L,即1s后开始重试 ;
—>multiplier:指定延迟的倍数,默认为0,比如delay=5000l,multiplier=2时,第一次重试为5秒后,第二次为10秒,第三次为20秒;
—>maxDelay:重试次数之间的最大时间间隔,默认为0,即忽略,如果小于delay的设置,则默认为30000L;

3 @Recover 注解

指定回调函数。
当重试耗尽时,Spring-Retry还提供了@Recover注解,用于@Retryable重试失败后处理方法,此方法里的异常一定要是@Retryable方法里抛出的异常,否则不会调用这个方法。

--重试耗尽后的回调函数,注意异常类型一定要是目标方法抛出的异常类型
@Recover
public int recover(Exception e) {
    // do something...
    return 0;
}

5 简单的完整示例

 这是注解最全的一个示例了,如果想要完整的实例,结合第三章一起看就行了
@Retryable(value= {Exception.class}, maxAttempts=4, backoff=@Backoff(delay = 1000l,maxDelay = 10 * 1000L, multiplier = 1))
public String targetMethod() throws Exception ();

说明:指定Exception及其子类的重试异常;最大重试次数为4;首次重试间隔1000ms;每次重试间隔10*1000ms;延迟倍数为1,即每次间隔为1000ms。