[英]Hooking into Grails Domain object save()
我正在写一个grails插件,我需要挂钩到域save()方法,以便在保存后做一些逻辑。 我需要在多个域类中执行此操作。 我试图避免在插件用户没有使用带有GORM的hibernate的情况下的hibernate事件。
我尝试了很多东西,但下面是我认为应该有最好的工作机会。 在所有情况下, grailsSave都为null 。 我怎样才能做到这一点?
def doWithDynamicMethods = { ctx ->
application.domainClasses.each { dc ->
def grailsSave = dc.metaClass.pickMethod('save', [Map] as Class[])
domainClass.metaClass.save = { Map params ->
grailsSave.invoke(delegate, [params] as Object[])
println "Saved object, now do my thing"
//...
}
}
}
我的* Plugin.groovy类中有以下设置:
def dependsOn = [domainClass: '1.1 > *', hibernate: '1.1 > *']
def loadAfter = ['hibernate']
在插件/应用程序初始化期间,我无法成功获得对save()方法的引用; 我不知道为什么。 相反,我决定在插入,更新和删除之后为hibernate事件创建一个监听器。 Sean Hartsock关于审计日志插件的这篇文章是这样做的完美入门。
这是听众的要点:
class MyListener implements PostInsertEventListener, PostUpdateEventListener, PostDeleteEventListener, Initializable {
public void onPostInsert(final PostInsertEvent event) {
// logic after insert
return
}
public void onPostUpdate(final PostUpdateEvent event) {
// logic after update
return
}
public void onPostDelete(final PostDeleteEvent event) {
// logic after delete
return
}
public void initialize(final Configuration config) {
return
}
}
然后在* GrailsPlugin.groovy中:
def doWithApplicationContext = { applicationContext ->
// add the event listeners for reindexing on change
def listeners = applicationContext.sessionFactory.eventListeners
def listener = new MyListener()
['postInsert', 'postUpdate', 'postDelete'].each({
addEventTypeListener(listeners, listener, it)
})
}
// copied from http://hartsock.blogspot.com/2008/04/inside-hibernate-events-and-audit.html
private addEventTypeListener(listeners, listener, type) {
def typeProperty = "${type}EventListeners"
def typeListeners = listeners."${typeProperty}"
def expandedTypeListeners = new Object[typeListeners.length + 1]
System.arraycopy(typeListeners, 0, expandedTypeListeners, 0, typeListeners.length)
expandedTypeListeners[-1] = listener
listeners."${typeProperty}" = expandedTypeListeners
}
在一天结束时相当简单......
metaClass中添加了三种不同版本的save,
save(Map)
save(Boolean)
save()
你在测试中打电话给哪一个? 您需要为每个代码添加代码。
要检查的另一件事是你的插件是否在hibernate插件之后运行,它将三种方法添加到metaClass
干杯
背风处
看看Falcone Util插件。 这个插件允许您挂钩Hibernate事件(请参阅页面底部的文档)。 我不知道这是不是你想要的,但你可能会得到一些提示。
诗篇! 我不认为该插件适用于Grails 1.2。
这是一个过早优化的问题:旧版本的Groovy严重损害了MetaClass的修改,因此GORM在检测到需要之前不会添加所有的魔法。
最简单的解决方案是让您的插件依赖于GORM实验室(我在那里解决)。 另一种解决方案是手动触发methodMissing(这将重复我所做的工作)。 有关如何完成该操作的详细信息,请参阅GORM实验室文档。
这不是最好添加到拥有工作单元的服务类吗? 这就是通常的Spring / Grails成语具有这样的逻辑的地方。 您根本无需修改保存。
其他GORM方法在第一次调用它们时会被懒惰地初始化。 要在doWithDynamicMethods
初始化它们,只需调用域类中的一个静态方法:
def doWithDynamicMethods = { ctx ->
application.domainClasses.each { dc ->
// call any static method to initialize dynamic gorm methods
dc.clazz.count()
def grailsSave = dc.metaClass.pickMethod('save', [Map] as Class[])
//...
}
}
您的save()方法现在可用。 由于这是在启动时调用的,因此单个计数不应该是一个大问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.