2

正如我在这里所读到的,grails 正在使用 methodMissing 将 GORM 方法注入到域类中,但是已经说过 methodMissing 执行起来很昂贵,因为仅在调度失败的情况下才会发生,为什么这些方法不通过 metaClass 或 AST 转换注入?有什么线索吗?

4

2 回答 2

7

使用 methodMissing 并不昂贵,因为 Grails 仅在第一次执行未找到的方法时才在 MOP 中创建新方法。后续执行发生在新创建的方法上。

考虑一个具有许多属性的域类。如果所有 findBy*、findAlLBy*、countBy* 等排列都应该在编译时创建,那么类很容易变得非常大。通过使用methodeMissing,只会创建在运行时实际使用的方法。

于 2012-12-04T09:59:30.423 回答
5

据我了解代码,此信息已过时。这些方法被注入到元类中。查看 grails-hiberante 插件的代码。

HibernateGrailsPlugin.groovy( github ) 每次上下文开始时执行第 49 行:

def doWithDynamicMethods = HibernatePluginSupport.doWithDynamicMethods

然后,打开一个HibernatePluginSupportgithub)并按照流程进行操作:

/*451*/ static final doWithDynamicMethods = { ApplicationContext ctx ->
    def grailsApplication = application
    enhanceSessionFactories(ctx, grailsApplication)
}

/*456*/ static void enhanceSessionFactories(ApplicationContext ctx, grailsApplication, source = null)
// calls in line 464:
/*464* enhanceSessionFactory sessionFactory, grailsApplication, ctx, suffix, datastores, source

这个闭包在方法内部是至关重要的enhanceSessionFactory

/*548*/ def enhanceEntity = ...

并且为第 581-583 行中的每个实体调用它。方法是从 method 中的第 587 行生成的registerNamespaceMethods。正如我正确理解的那样,这些方法从第 597 行直接注入到 metaClass:

    def classLoader = application.classLoader

    def finders = HibernateGormEnhancer.createPersistentMethods(application, classLoader, datastore)
    def staticApi = new HibernateGormStaticApi(dc.clazz, datastore, finders, classLoader, transactionManager)
    dc.metaClass.static."$getter" = { -> staticApi }

    def validateApi = new HibernateGormValidationApi(dc.clazz, datastore, classLoader)
    def instanceApi = new HibernateGormInstanceApi(dc.clazz, datastore, classLoader)
    dc.metaClass."$getter" = { -> new InstanceProxy(delegate, instanceApi, validateApi) }

如果我错了,请修改并纠正我。我不太相信这一切都是正确的。这些只是我在阅读 Grails 源代码时的发现。

于 2012-12-04T10:16:37.613 回答