2025年2月7日 spring-retry

参考

引言

一直想学习下 spring-retry,不过之前的工作中一直没有用到,也就一直拖下来了直到现在。

虽然之前有看到一些相关文章,但是这个项目本身的引用量好像也不是很大。

spring-retry 更像一个小工具,没有 spring framework 那样的官方文档网页,如果需要深入学习,可以直接看 github 库上的文档

下面写了一个小demo,感觉确实在 spring 项目中,如果需要重试的场景,使用起来代码确实很简洁优雅。

用法上类似于 Spring 事务,同样有编程式和注解式两种用法,同样的更倾向于注解式使用方法

示例

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>study.hwj</groupId>
    <artifactId>study-spring-retry</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
            <version>2.0.4</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.0.11</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.11</version>
        </dependency>

    </dependencies>
</project>

spring配置类

package study.hwj;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

@ComponentScan
@Configuration
@EnableRetry
public class AppConfig {
    

    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();

        FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
        fixedBackOffPolicy.setBackOffPeriod(2000L);
        retryTemplate.setBackOffPolicy(fixedBackOffPolicy);

        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(2);
        retryTemplate.setRetryPolicy(retryPolicy);

        retryTemplate.registerListener(new MyRetryListener());

        return retryTemplate;
    }
}

监听器

package study.hwj;

import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.stereotype.Component;

@Component
public class MyRetryListener implements RetryListener {

    @Override
    public <T, E extends Throwable> boolean open(RetryContext context,
                                                 RetryCallback<T, E> callback) {
        System.out.println("onOpen");
        // return super.open(context, callback);
        return true;
    }

    @Override
    public <T, E extends Throwable> void close(RetryContext context,
                                               RetryCallback<T, E> callback, Throwable throwable) {
        System.out.println("onClose");
        // super.close(context, callback, throwable);
    }

    @Override
    public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        System.out.println("onError");
        // super.onError(context, callback, throwable);
    }

    @Override
    public <T, E extends Throwable> void onSuccess(RetryContext context, RetryCallback<T, E> callback, T result) {
        System.out.println("onSuccess");
    }
}

业务类,直接使用 RetryTemplate

package study.hwj;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component;

@Component
public class RetryService {
    @Autowired
    public RetryTemplate retryTemplate;

    static int count = 0;

    public void doRetry() {
        retryTemplate.execute(context -> {
            System.out.println("start 1...");

            if (count < 2) {
                System.out.println("count is " + count);
                count++;
                throw new RuntimeException("1");
            }


            System.out.println("end 1...");

            return "xx";
        });
    }
}

业务类,使用注解

package study.hwj;

import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

@Component
public class RetryServiceWithAnnotation {


    static int count = 0;

    @Retryable(retryFor = RuntimeException.class, maxAttempts = 5)
    public void doRetry() {
        System.out.println("start 1...");

        if (count < 4) {
            System.out.println("count is " + count);
            count++;
            throw new RuntimeException("1");
        }


        System.out.println("end 1...");
    }
}

测试类

package study.hwj;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

        // 两种使用方式,类似于Spring事务的使用
        // 1. 编程式:直接用RetryTemplate
        // RetryService retryService = applicationContext.getBean(RetryService.class);
        // retryService.doRetry();

        // 2. 注解式: @EnableRetry + @Retryable ,不需要定义 RetryTemplate
        RetryServiceWithAnnotation retryService = applicationContext.getBean(RetryServiceWithAnnotation.class);
        retryService.doRetry();

    }
}
posted @   流星<。)#)))≦  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2017-02-07 使用JDBC进行批处理
点击右上角即可分享
微信分享提示