@Recover(后备方法)在与@CircuitBreaker 一起使用时不会被调用,一旦所有重试都用完

@Recover (fallback method) is not getting invoked when used with @CircuitBreaker, once all the retry gets exhaused

尽管使用其他 return 类型的 Spring 重试回退机制似乎工作正常,但是当涉及到使用 return 类型调用 void 的 API 时。恢复方法根本没有被调用,我尝试了所有可能的方法参数类型并更改了后备方法的 return 类型....有什么办法吗?我不明白为什么 @CircuitBReaker 注释没有参数来将回退方法名称作为值传递给它?

    @CircuitBreaker(maxAttempts = 3, openTimeout = 8000, resetTimeout = 15000)
    public Void callingXYZ(final Abc abc, final Cdf cdf) {
        return retryTemplate.execute(context -> {
            log.info("Retry count={} when calling ******", context.getRetryCount());
            AbcServiceImpl.this.update*****Settings(OrgId.fromString(abc.getUUID(), cdf.getData());
            return null;
        });
    }

   //Recover method that should get invoked
    @Recover
    public Void fallbackUpdate*****(Throwable e, Abc abc) throws Throwable{
        log.info("Inside fallback");
        if (e instanceof ClientException) {
            log.warn("Fallback method is called when trying to call ******** from ****** because of {}", e.getCause());

   //Rollback in the db based on the method attributes
            throw SpecificException.forTask(HttpStatus.SERVICE_UNAVAILABLE.value(),
                    Enum.NAME.getErrorCode(),
                    Enum.NAME.getMEssage(), true);
        }
        throw e;
    } 

尝试使用 @Retryable 它对我有用

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

@Retryable(value = { NullPointerException.class},maxAttempts = 2)
public void retry() throws NullPointerException{
    throw new NullPointerException("something went wrong");
}

@Recover
public void recover(NullPointerException ex)
{
    System.out.println("iniside recover");
}

有关详细信息,请查看此 link https://www.baeldung.com/spring-retry

我在我的代码中解决了这个问题,它与 spring-retry 项目无关。由于我对 AOP 的 Spring 实现缺乏了解,我无法找到问题的解决方案。由于 Spring 的方面应用于 bean 周围的代理而不是实际的 class,如果从相同的 class/Service 调用带有 @circuitbreaker 的方法将无法工作。 =10=]

您是否曾经使用@Transactional(或例如@Async)对方法进行注释但它不起作用?好像完全被Spring忽略了一样?这是因为像这样的注释不能(至少在默认情况下)只放在任何方法上,必须满足以下两个条件才能让 Spring 采取行动:

方法可见性只能是public。 调用必须来自 bean 外部。 这是由于 Spring 默认情况下代理的工作方式(使用 CGLIB 代理)。我不会深入细节,因为它是一个足够广泛的话题来写另一篇文章,但一般来说,当你自动装配一个 Sample 类型的 bean 时,Spring 实际上并没有为你提供一个 Sample 的实例.相反,它注入了一个生成的代理 class,它扩展了 Sample(这就是为什么你不能让你的 spring bean classes final 的原因)并覆盖它的 public 方法是能够添加额外的行为(如事务支持)。

这就是为什么带有@Transactional 的方法必须是public(所以Spring 可以很容易地覆盖它们)也是为什么调用必须来自外部(只有这样它才能通过代理, Spring 无法将此引用替换为代理引用)。

取自https://codete.com/blog/5-common-spring-transactional-pitfalls/