@PostConstruct 在 Grails 服务上静默失败
Posted
技术标签:
【中文标题】@PostConstruct 在 Grails 服务上静默失败【英文标题】:@PostConstruct fails silently on a Grails Service 【发布时间】:2013-01-27 17:26:58 【问题描述】:我认为 Spring 注释应该在 Grails 环境中开箱即用,但我根本无法让它工作。我也尝试了 afterProperties 方法,但也没有用。
谁能发现错误?我需要做一些配置吗?
package dashboard
import javax.annotation.PostConstruct
class EmailJobSchedulerService
def grailsApplication
@PostConstruct
def init()
def cronExpression = grailsApplication.config.emailAt8AmTrigger
println(cronExpression)
EmailSubscribersJob.schedule(cronExpression, new HashMap())
【问题讨论】:
该注释设置了很多约束(请参阅docs.oracle.com/javase/7/docs/api/javax/annotation/…)。它们都适用吗? @lucke84 根据 Ian 的建议将其更改为 void 后,我应该遵守所有约束 您希望何时打印 cronExpression?在服务器启动?我相信这是在第一次调用任何服务方法时调用的,而不是在服务器启动时调用的。我建议在引导程序中调用一个虚拟方法来确认。 @uchamp 我希望在 Spring 完成配置我的 bean 时调用它 【参考方案1】:试试改成
@PostConstruct
void init()
(即void
而不是def
)。我不确定 Spring 是否专门强制执行此操作,但 specification of @PostConstruct
指出“方法的返回类型必须为 void”。
编辑:uchamp 的评论是正确的,我只是尝试了相同的测试,实际上 @PostConstruct
注释方法仅在第一次使用服务 bean 时调用,不一定在启动时立即调用。你可以添加
static lazyInit = false
到服务类以强制它在启动时急切地初始化。这似乎没有记录在用户指南中,我是通过reading the code 推断出来的。
请注意,上一段中的“使用”并不一定意味着您必须在其上调用方法。服务 bean 将在第一次从应用程序上下文中获取时被初始化,无论是直接还是因为它已自动装配到另一个正在初始化的 bean 中。例如,使用
将服务注入BootStrapdef emailJobSchedulerService
足以触发@PostConstruct
方法,您不必从BootStrap.init
闭包中实际调用任何服务方法。同样,如果您的服务被注入任何控制器,那么 init 将在其中一个控制器第一次处理请求时触发(任何请求,它不必是调用服务的操作)。
【讨论】:
还是什么都没有。不过感谢您的努力:) @willcodejavaforfood 假设有问题的.groovy
文件位于grails-app/services
而不是src/groovy
,那么它应该正常工作。我多次使用相同的技巧。不过要注意的一件事是 GORM 在@PostConstruct
时间可能不可用。如果您需要对 GORM 方法做任何事情,您可能必须定义一个普通的非注释方法并从 BootStrap 中调用它。
这很奇怪。甚至只使用命令行创建了一个全新的项目,也没有在那里调用@PostConstruct。我不需要为此使用 GORM,只需安排我没有持久化的作业。
@willcodejavaforfood 经过一番挖掘后,看起来 static lazyInit = false
就是您要找的东西。
太棒了!不知道这个选项。【参考方案2】:
只是添加来自@Ian 的答案 - 出于某种原因,我有:
@PostConstruct
private void init()
这也默默地失败并给出了奇怪的行为。解决方案是删除“私人”:
@PostConstruct
void init()
【讨论】:
以上是关于@PostConstruct 在 Grails 服务上静默失败的主要内容,如果未能解决你的问题,请参考以下文章
@PostConstruct方法的使用以及原理,@Component+@PostConstruct方法将一个方法完成初始化操作