我有一个Groovy类,可以动态创建另一个类:
package javainterop3
import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader;
class DynamicClass {
GroovyClassLoader loader
String name
Class cls
def imports
def fields
def methods
def DynamicClass() {
imports = []
fields = [:]
methods = [:]
}
def setLoader(GroovyClassLoader loader)
{
this.loader = loader
}
def setName(String name) {
this.name = name
}
def setImports(Set imports) {
this.imports = imports.each{importClass ->
"${importClass.getPackage().getName()}" +
".${importClass.getSimpleName()}"
}
}
def addFields(Map fields) {
this.fields = fields
}
def addMethods(Map methods) {
this.methods = methods
}
def createClass() {
def templateText = '''
<%imports.each {%>import $it\n <% } %>
class $name
{
<%fields.each {%> $it.value $it.key \n<% } %>
}
'''
fields.each {
it.value = it.value.simpleName
}
def data = [name: name, imports: imports, fields: fields]
def engine = new groovy.text.SimpleTemplateEngine()
def template = engine.createTemplate(templateText)
def result = template.make(data)
println result.toString()
cls = loader.parseClass(result.toString())
methods.each {
cls.metaClass."$it.key" = it.value
}
}
}
我现在正在尝试为创建新类创建一个简单的生成器:
package javainterop3
import java.util.Map;
class ClassBuilder extends BuilderSupport{
private DynamicClass dynamicClass
@Override
protected void setParent(Object parent, Object child) {
}
@Override
protected Object createNode(Object name) {
if(name == 'newClass')
{
dynamicClass = new DynamicClass()
}
else
{
throw new IllegalArgumentException(name)
}
}
@Override
protected Object createNode(Object name, Object value) {
if(name == 'loader')
{
dynamicClass.setLoader(value)
}
else if(name == 'name')
{
dynamicClass.setName(value)
}
else if(name == 'imports')
{
println value
dynamicClass.setImports(value)
}
else
{
throw new IllegalArgumentException(name)
}
}
@Override
protected Object createNode(Object name, Map attributes) {
if(name == 'fields')
{
dynamicClass.setFields(attributes)
}
else if(name == 'methods')
{
dynamicClass.setMethods(attributes)
}
else
{
throw new IllegalArgumentException(name)
}
}
@Override
protected Object createNode(Object name, Map attributes, Object value) {
return null
}
@Override
protected void nodeCompleted(Object parent, Object node)
{
if(node instanceof DynamicClass)
{
node.createClass()
}
}
public Class getDynamicClass()
{
return dynamicClass.cls
}
}
这是一个创建简单的Groovy类的测试脚本:
package javainterop3
import java.util.Calendar
import java.util.Random
def builder = new ClassBuilder()
builder.newClass{
loader this.class.classLoader
name 'MyClass'
imports Calendar, Random, UUID
fields 'field1' : Integer,
'field2' : Integer
methods 'sum' : {return field1 + field2},
'product' : {return field1 * field2},
'testCalendar' : {return Calendar.getInstance().getTime()},
'testRandom' : {return (new Random()).nextInt()}
}
我的问题是使用
imports
方法。应该接受要导入的Java类的列表。在基础类(DynamicClass)中,导入是一个列表,但我不确定如何将列表传递给构建器,或者不确定createNode()重载来处理imports
方法。我以为参数不是在createNode(Object name,Object value)中处理它的映射,但是我得到了这个异常:Caught: groovy.lang.MissingMethodException: No signature of method: \
javainterop3.Test.imports() is applicable for argument types: \
(java.lang.Class, java.lang.Class, java.lang.Class) values: \
[class java.util.Calendar, class java.util.Random, ...]
“加载程序”和“名称”在createNode(对象名称,对象值)中被拦截,在createNode(对象名称,地图属性)中的“字段”和“方法”中被拦截,但是我不确定如何处理“导入”一个列表。我已经尝试过每个createNode重载,但无法使其工作。
最佳答案
它与重写的方法不匹配。一种方法是进行以下修改:
//Dynamic Class
def setImports(Class importClass) {
this.imports << "$importClass.name"
}
然后在建造时
builder.newClass{
loader this.class.classLoader
name 'MyClass'
[Calendar, UUID, Random].each { imports it }
fields 'field1' : Integer,
'field2' : Integer
methods 'sum' : {return field1 + field2},
'product' : {return field1 * field2},
'testCalendar' : {return Calendar.getInstance().getTime()},
'testRandom' : {return (new Random()).nextInt()}
}