我想在 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
这样的注释)。任何指导或建议将不胜感激。
谢谢!
该问题是由我的自定义
@Transactional
注释上的 @CustomService
注释引起的。由于 @Transactional
代理类来处理事务管理,因此与 @Service
结合时会干扰重试机制。重试逻辑应用于事务代理,这可能导致方法调用在第一次调用后绕过重试逻辑。