Java 为什么可以';t@PostConstruct和@Retryable可以一起使用吗?
我使用Java 为什么可以';t@PostConstruct和@Retryable可以一起使用吗?,java,spring,spring-aop,spring-aspects,spring-retry,Java,Spring,Spring Aop,Spring Aspects,Spring Retry,我使用注释ConfigApplicationContext创建了一个基于spring框架的应用程序 一个bean有一个init方法,它创建到外部服务的连接。这可以用@PostConstruct进行注释,以便在启动bean后自动运行,从而起作用 为了在创建此连接时处理任何异常,如果捕获到异常,我希望我的init方法最多重试5次。当同时使用@PostConstruct和@Retryable对方法进行注释时,我看到异常被抛出一次,并且程序退出-看起来@Retryable没有任何效果 我已在配置类中正确
注释ConfigApplicationContext
创建了一个基于spring框架的应用程序
一个bean有一个init方法,它创建到外部服务的连接。这可以用@PostConstruct
进行注释,以便在启动bean后自动运行,从而起作用
为了在创建此连接时处理任何异常,如果捕获到异常,我希望我的init方法最多重试5次。当同时使用@PostConstruct
和@Retryable
对方法进行注释时,我看到异常被抛出一次,并且程序退出-看起来@Retryable
没有任何效果
我已在配置类中正确使用了@enablerery
,以及@configuration
。我在同一个bean上创建了另一个方法B,该方法被注释为可重试,如果在实例化bean后调用该方法,我可以看到该方法在抛出异常时得到重试/表现出预期的行为
我的想法可能与方面有关,或者后构造发生在SpringRetry元素连接之前
有没有更好的方法来拥有一个可以处理异常并通过注释可检索的初始化方法,而不是在该方法中以编程方式进行尝试
编辑:我现在同意不应该通过@Postconstruct
创建到外部服务的连接。如果重试失败,这会阻止整个上下文初始化,从而产生有害影响
但是,这还不能回答Spring框架的哪个部分不允许这两个注释一起工作的问题。我建议您实际应用一个
ApplicationListener
,它侦听ContextRefreshedEvent
,并用您的重试逻辑对该方法进行注释。一旦上下文完全刷新,并且所有bean都已正确配置和连接,就会触发这些侦听器
为了在创建此连接时处理任何异常,如果捕获到异常,我希望我的init方法最多重试5次
永远不要连接到init方法中的资源;您应该先等待上下文的创建
最好实现SmartLifecycle
并连接到start()
。这样,您就可以确保在开始连接到外部资源之前,整个上下文都已初始化
这样,重试拦截器应该通知start()
方法
正如@Naros所建议的,
ContextRefreshedEvent
是另一种选择,但您永远不应该在@PostConstruct
中做类似的事情。“@Retryable”是“spring retry”应用的一个方面。这只有在完全创建spring上下文后才会附加,毕竟“@PostConstruct”注释的方法会运行,因此“@Retryable”无效。将PostConstruct替换为EventListener({ContextRefreshedEvent.class})并与Retryable结合使用,可以提供我想要的行为。我相信在一个应用程序生命周期中,上下文可以被刷新多次,因此它可能不是我正在寻找的解决方案。创建连接的方法应该只运行一次,并重试X次。是的,上下文可以刷新多次,但每次刷新时,bean都会在spring上下文中重新创建,因此不管您想做什么,它都会为您提供所需的行为。谢谢您的建议,Gary。但下一步该怎么办呢connectinstart()
–如何将此连接传递到特定bean?在阅读您的答案之前,我一直想在PostConstruct
中获得连接(在我的例子中:curr hazelcast实例),尝试5次。不要在评论中提出新问题。只需将代码从post-construct方法移动到smartlifecycle.start()
。如果这还不够,问一个新问题。我认为下面的@BetoNeto是一个更好的答案,任何问题最简单的答案就是停止这个问题。我认为最好的答案是OP提供的答案,因为他解释了内部部分。现在该由读者运用他认为最好的知识了。