为什么GORM使用methodMissing

Dav*_*ria 2 grails groovy metaprogramming abstract-syntax-tree grails-orm

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

sbg*_*ius 7

使用methodMissing并不昂贵,因为Grails只在第一次执行未找到的方法时才在MOP中创建一个新的方法.子序列执行发生在新创建的方法上.

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


Tom*_*ski 5

据我了解代码,此信息已过时.这些方法被注入metaClasses.看一下grails-hiberante插件的代码.

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

def doWithDynamicMethods = HibernatePluginSupport.doWithDynamicMethods
Run Code Online (Sandbox Code Playgroud)

然后,打开一个HibernatePluginSupport(github)并按照流程:

/*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
Run Code Online (Sandbox Code Playgroud)

这种封闭在enhanceSessionFactory方法中至关重要:

/*548*/ def enhanceEntity = ...
Run Code Online (Sandbox Code Playgroud)

并且在第581-583行中为每个实体调用它.从方法中的第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) }
Run Code Online (Sandbox Code Playgroud)

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