如何在不修改服务类的情况下使用Spring AOP实现应用级重试逻辑?

问题描述 投票:0回答:1

我想在 Spring Boot 应用程序中实现应用程序级别的重试机制。但是,我不想添加

@Retryable
或对服务方法或其类进行任何更改。我的目标是使用 Spring AOP 和集中配置(例如
RetryTemplate
)来实现重试逻辑,以实现整个应用程序的一致性。

这是我到目前为止所做的:

方面类 我创建了一个方面,使用

RetryTemplate
处理
@Service
类中所有方法的重试。

@Aspect
@Component
public class DbConnectionRetryAspect {

    private final RetryTemplate retryTemplate;

    public DbConnectionRetryAspect(RetryTemplate retryTemplate) {
        this.retryTemplate = retryTemplate;
    }

    @Around("@within(org.springframework.stereotype.Service)")
    public Object retry(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Aspect invoked for method: " + joinPoint.getSignature());

        return retryTemplate.execute(context -> {
            System.out.println("Retry attempt: " + context.getRetryCount());
            try {
                return joinPoint.proceed();
            } catch (SQLTransientConnectionException e) {
                System.out.println("Retryable exception caught: " + e.getMessage());
                throw e; // Ensure the exception propagates for retries
            }
        });
    }
}

重试模板配置 我创建了一个

RetryTemplate
bean 来定义重试逻辑。

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

    SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(
        5,  // maxAttempts
        Map.of(SQLTransientConnectionException.class, true)
    );
    retryTemplate.setRetryPolicy(retryPolicy);

    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
    backOffPolicy.setBackOffPeriod(1000); // 1 second
    retryTemplate.setBackOffPolicy(backOffPolicy);

    return retryTemplate;
}

服务等级 当操作失败时,服务方法会抛出

SQLTransientConnectionException
。我不想用
@Retryable
来注释这个方法。

@Service
public class MyService {

    public void performOperation() throws SQLTransientConnectionException {
        System.out.println("Service method invoked");
        throw new SQLTransientConnectionException("Simulated transient error");
    }
}

配置 我添加了以下配置来启用 AspectJ:

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AspectJConfig {
}

问题: 调用方面时,重试逻辑未按预期工作。具体来说:

  • RetryTemplate
    日志表明已尝试重试(重试尝试:X),但服务方法仅被调用一次。

  • 似乎异常没有正确传播,或者重试逻辑没有应用于服务方法。

我需要什么帮助: 如何使用 Spring AOP 和

RetryTemplate
实现应用程序级重试逻辑,以便:

  • 重试机制按预期工作。
  • 服务类或方法不需要进行任何更改(例如,不需要像
    @Retryable
    这样的注释)。
  • 重试尝试和退避策略可通过集中式 RetryTemplate 进行配置。

任何指导或建议将不胜感激。

谢谢!

java spring spring-boot microservices spring-aop
1个回答
0
投票

该问题是由我的自定义

@Transactional
注释上的
@CustomService
注释引起的。由于
@Transactional
代理类来处理事务管理,因此与
@Service
结合时会干扰重试机制。重试逻辑应用于事务代理,这可能导致方法调用在第一次调用后绕过重试逻辑。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.