为什么不能同时使用@PostConstruct和@Retryable?

时间:2016-07-03 19:07:46

标签: java spring spring-aop spring-aspects spring-retry

我使用AnnotationConfigApplicationContext创建了一个基于Spring框架的应用程序。

一个bean有一个init方法,它创建一个到外部服务的连接。这可以用@PostConstruct注释,一旦bean启动就可以自动运行。

要在创建此连接时处理任何异常,我希望我的init方法在捕获异常时最多重试5次。使用@PostConstruct@Retryable注释方法时,我看到异常被抛出一次并且程序退出 - 看起来@Retryable没有效果。

我在配置类中正确使用了@EnableRetry@Configuration。我在同一个bean上创建了另一个方法B,注释为可重试,如果在实例化bean之后调用此方法,我可以看到方法在抛出异常时按预期重试/行为。

我对于为什么这不起作用的想法可能是与方面有关的事情,或者是在弹簧重试元素附加之后发生了postconstruct?

实际上有一种更好的方法可以使用初始化方法来处理异常并通过注释进行重试 - 而不是在方法中以编程方式进行尝试吗?

编辑:我现在同意不应通过@Postconstruct创建与外部服务的连接。如果重试失败可能会产生不利影响,这可以阻止整个上下文初始化。

然而,这还没有回答Spring框架的哪个部分不允许这两个注释一起工作的问题。

3 个答案:

答案 0 :(得分:2)

  

要在创建此连接时处理任何异常,我希望我的init方法在捕获异常时最多重试5次。

你永远不应该在init方法中连接资源;你应该等待首先创建上下文。

实施SmartLifecycle并在start()中进行连接要好得多。这样,您可以确保在开始连接外部资源之前已初始化整个上下文。

这样,重试拦截器应该建议start()方法。

正如@Naros建议的那样,ContextRefreshedEvent是另一种选择,但你永远不应该在@PostConstruct中做类似的事情。

答案 1 :(得分:1)

我建议您实际应用一个ApplicationListener来监听ContextRefreshedEvent,并使用您的重试逻辑对此方法进行注释。一旦上下文完全刷新并且所有bean都已正确配置并连接,就会触发这些侦听器。

答案 2 :(得分:-1)

' @可重试'是弹簧重试所应用的一个方面。这仅在完全创建弹簧上下文后才会附加,这毕竟是@ PostConstruct'注释方法因此运行' @ Retryable'没有效果。