Japanese Plugin Dynamic Methods

Last updated by admin 4 years ago

????????????????{excerpt:hidden=true}Adding dynamic methods at runtime{excerpt}

??{excerpt:hidden=true}The Basics{excerpt}

Grails????????Grails???????????????????????????????????????????? ??????????????? {{doWithDynamicMethods}} ?????????????????????????????????????????????????????????????????????????????????{excerpt:hidden=true} Grails plugins allow you to register dynamic methods with any Grails managed or other class at runtime. New methods can only be added within a {{doWithDynamicMethods}} closure of a plugin. After which no new methods can be added. This is to ensure thread safety when using dynamic methods.{excerpt} ????????????????????ExpandoMetaClass???????????????????????????????Grails???????????????????????????????????????:{excerpt:hidden=true} For Grails managed classes like controllers, tag libraries and so forth you can add methods, constructors etc. using the ExpandoMetaClass mechanism by accessing each controller's MetaClass:{excerpt}

class MyPlugin {

def doWithDynamicMethods = { applicationContext ->

application.controllers.metaClass.each { metaClass -> metaClass.myNewMethod = {-> println "hello world" } } } }

Grails?????????????????????ExpandoMetaClass????????????????????????????????????????????????????ExpandoMetaClass????????initialize()?????:{excerpt:hidden=true} For other classes you will need to create an ExpandoMetaClass explicitly, register methods and then call initialize() on the ExpandoMetaClass so that it can be used:{excerpt}
class MyPlugin {

def doWithDynamicMethods = { applicationContext -> Class someClass = .. // load from somewhere

def metaClass = new ExpandoMetaClass(someClass, true) metaClass.myNewMethod = {-> println "hello world" }

metaClass.initialize()

} }

ApplicationContext????{excerpt:hidden=true}Interacting with the ApplicationContext{excerpt}

{{doWithDynamicMethods}} ??????Spring?ApplicationContext????????????????????ApplicationContext?????????????????????????????????Hibernate??????????????????????HibernateTemplate?????SessionFactory?????????????????:{excerpt:hidden=true} The {{doWithDynamicMethods}} closure gets passed the Spring ApplicationContext instance. This is useful as it allows you to interact with objects within it. For example if you were implementing a method to interact with Hibernate you could use the SessionFactory instance in combination with a HibernateTemplate:{excerpt}

code: null
import org.springframework.orm.hibernate3.HibernateTemplate

class MyHibernatePlugin {

def doWithDynamicMethods = { applicationContext ->

application.domainClasses.metaClass.each { metaClass ->

metaClass.myNewPersistentMethod = { ->

def sf = applicationContext.sessionFactory def ht = new HibernateTemplate(sf)

// do something with HibernateTemplate } } } }

code: null
??Spring?????autowire?dependency injection?????????????????????????????????????????????????????????????????????????????:{excerpt:hidden=true} Also because of the autowiring and dependency injection capability of the Spring container you can implement more powerful dynamic constructors that use the application context to wire dependencies into your object at runtime:{excerpt}
class MyConstructorPlugin {

def doWithDynamicMethods = { applicationContext ->

application.domainClasses.each { domainClass ->

domainClass.metaClass.ctor = {-> return applicationContext.getBean(domainClass.name) } }

} }