加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 动态创建Groovy类

发布时间:2020-12-15 04:19:34 所属栏目:Java 来源:网络整理
导读:给定一个类名,我想动态创建一个Groovy类,为它添加属性和方法.我使用创建新类 instance = this.class.classLoader.parseClass( "public class $name {}") 对于我使用的方法 instance.metaClass."$it.key" = it.value 其中it.key是一个字符串(方法名称),it.val
给定一个类名,我想动态创建一个Groovy类,为它添加属性和方法.我使用创建新类

instance = this.class.classLoader.parseClass(
                "public class $name {}")

对于我使用的方法

instance.metaClass."$it.key" = it.value

其中it.key是一个字符串(方法名称),it.value是一个闭包.这很方便,因为我可以指定方法参数类型并获取类型检查.但是,如果没有为其赋值,我无法指定动态创建的属性类型.我可以通过明确定义属性的getter和setter来解决这个问题.这样可行,但似乎metaClass.name = value和metaClass.getName = {}实际上都没有在类中创建字段,因为Java字段运算符不适用于创建的属性.我可以将属性添加到Groovy类并指定其类型,而无需为其分配初始值或显式定义getter和setter方法吗?有没有办法向Groovy类添加新字段?
这是脚本:

class SomeClass {
    Integer p1
    String p2
}

class ClassBuilder {
    def name
    def instance
    def properties
    def methods

    def ClassBuilder() {
        properties = [:]
        methods = [:]
    }

    def set_name(name) {
        this.name = name
    }

    def add_property(name,type) {
        properties[name] = type
    }

    def add_method(name,closure) {
        methods[name] = closure
    }

    def get_instance() {
        instance = this.class.classLoader.parseClass(
                "public class $name {}")

        properties.each {
            instance.metaClass."$it.key" = null
            //doesn't work
            instance.metaClass."$it.key".type = it.value
        }

        methods.each {
            instance.metaClass."$it.key" = it.value
        }

        return instance
    }
}

builder = new ClassBuilder()

builder.set_name('MyClass')

builder.add_property('property1',String)
builder.add_property('property2',SomeClass)

builder.add_method('method1',{SomeClass obj -> println obj})
builder.add_method('setProperty2',{SomeClass obj -> this.property2 = obj})
builder.add_method('getProperty2',{return this.property2})

builder.add_method('method2',{return property1 + property2})

c = builder.get_instance()

i = c.newInstance()
i.property1 = new SomeClass()
i.property2 = 5

//i.method2() //throws GroovyCastException

//i.property2 = 'throws GroovyCastException'
//i.@property1 = 'throws MissingFieldException'

//No such field: property2 for class: MyClass
//i.@property2 = new SomeClass()

i.method1(new SomeClass())
//i.method1('throws MissingMethodException')

[编辑]

用例是这样的:我在Java中定义了一个接口或基类.用户在Groovy中实现接口或扩展基类,并将类传递回Java以供主应用程序使用.用户不是程序员,因此他们使用简单的DSL定义类,并使用构建器构造实际的类.我还在尝试使用Groovy / JRuby和Java interop(两种语言都是新的).

解决方法

通过使用GroovyClassLoader和SimpleTemplateEngine,我或多或少能够使它工作.这是代码:

class ClassBuilder {

    GroovyClassLoader loader
    String name
    Class cls
    def imports
    def fields
    def methods

    def ClassBuilder(GroovyClassLoader loader) {
        this.loader = loader
        imports = []
        fields = [:]
        methods = [:]
    }

    def setName(String name) {
        this.name = name
    }

    def addImport(Class importClass) {
        imports << "${importClass.getPackage().getName()}" +
                ".${importClass.getSimpleName()}"
    }

    def addField(String name,Class type) {
        fields[name] = type.simpleName
    }

    def addMethod(String name,Closure closure) {
        methods[name] = closure
    }

    def getCreatedClass() {

        def templateText = '''
<%imports.each {%>import $itn <% } %> 
class $name
{
<%fields.each {%>    $it.value $it.key n<% } %>
}
'''
        def data = [name: name,imports: imports,fields: fields]

        def engine = new groovy.text.SimpleTemplateEngine()
        def template = engine.createTemplate(templateText)
        def result = template.make(data)
        cls = loader.parseClass(result.toString())
        methods.each {
            cls.metaClass."$it.key" = it.value
        }
        return cls
    }
}

以下是我如何使用它动态创建类的示例:

import java.util.Calendar
def builder = new ClassBuilder(this.class.classLoader)
builder.setName("MyClass");

builder.addImport(Calendar)

builder.addField('field1',Integer)
builder.addField('field2',Integer)

builder.addMethod('sum') { field1 + field2 }

builder.addMethod('product') { field1 * field2 }

builder.addMethod('testCalendar') {
    println Calendar.getInstance().getTime()
}

Class myClass = builder.getCreatedClass()
def myInstance = myClass.newInstance()

myInstance.field1 = 1
myInstance.field2 = 2

println myInstance.sum()
println myInstance.product()

myInstance.setField2(1500)
println myInstance.getField2()

myInstance.testCalendar()

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读