Spring 重试在 RestController 中不工作

Spring retry not working in RestController

我正在尝试 spring 重试,但我遇到了一个奇怪的问题。当我在 Rest Controller 中的方法上使用重试注释时,重试不起作用。但是,如果我将该方法移至单独的服务 class,它就会起作用。以下代码不起作用:

@RestController
public class HelloController {

    @RequestMapping(value = "/hello")
    public String hello() {
        return getInfo();
    }

    @Retryable(RuntimeException.class)
    public String getInfo() {
        Random random = new Random();
        int r = random.nextInt(2);
        if (r == 1) {
            throw new RuntimeException();
        } else {
            return "Success";
        }
    }
}

但以下内容确实如此:

@RestController
public class HelloController {

    @Autowired
    private SomeService service;

    @RequestMapping(value = "/hello")
    public String hello() {
        String result = service.getInfo();
        return result;
    }
}

@Service
public class SomeService {

    @Retryable(RuntimeException.class)
    public String getInfo() {
        Random random = new Random();
        int r = random.nextInt(2);
        if (r == 1) {
            throw new RuntimeException();
        } else {
            return "Success";
        }
    }
}

我的问题是为什么 @Retryable 在控制器中使用时不起作用?

您遇到的问题是由于您调用 getInfo() 方法的方式所致。

在第一个示例中,您从同一个 spring 托管 bean 中调用 getInfo()。在第二个示例中,您从不同的 spring 托管 bean 调用 getInfo()。这种区别很微妙,但非常重要,很可能是导致您出现问题的原因。

当您使用 @Retryable 注释时,Spring 正在围绕您的原始 bean 创建一个代理,以便它们可以在特殊情况下进行特殊处理。在这种特定情况下,Spring 应用一个 Advice,它将调用委托给您的实际方法,捕获它可能抛出的 RuntimeException,并根据您的 @Retryable 注释.

此代理在您的案例中很重要的原因是只有外部呼叫者才能看到代理建议。您的 bean 不知道它已被代理,只知道它的方法正在被调用(通过代理建议)。当您的 bean 调用自身的方法时,不会涉及进一步的代理,这就是为什么实际上不会重试的原因。