当我阅读here时,grails正在使用methodMissing将GORM方法注入到域类中,但是已经说过,执行代价很有代价,因为只有在调度失败的情况下才会发生,为什么不注入这些方法通过metaClass或AST转换?有线索吗?
答案 0 :(得分:7)
使用methodMissing并不昂贵,因为Grails只在第一次执行未找到的方法时才在MOP中创建一个新的方法。子序列执行发生在新创建的方法上。
考虑具有许多属性的域类。如果所有findBy *,findAlLBy *,countBy *等排列都应该在编译时创建,那么这些类很容易变得非常大。通过使用methodeMissing,将只创建在运行时实际使用的方法。
答案 1 :(得分:5)
据我了解代码,此信息已过时。这些方法被注入metaClasses。看一下grails-hiberante插件的代码。
每次上下文开始时, HibernateGrailsPlugin.groovy
(github)第49行执行:
def doWithDynamicMethods = HibernatePluginSupport.doWithDynamicMethods
然后,打开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
此封闭在enhanceSessionFactory
方法中至关重要:
/*548*/ def enhanceEntity = ...
并且在第581-583行中为每个实体调用它。从方法registerNamespaceMethods
中的第587行生成方法。正如我理解的那样,这些方法直接从第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源代码时的发现。