我正在尝试使用groovy编写一个注释和ASTTransformation来创建一个内部类。
以下是注释:
import org.codehaus.groovy.transform.GroovyASTTransformationClass;
import java.lang.annotation.*;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@GroovyASTTransformationClass("WithInnerClassTransformation")
public @interface WithInnerClass {
public String name();
}
转型:
import org.codehaus.groovy.ast.*;
import org.codehaus.groovy.control.*;
import org.codehaus.groovy.transform.*;
@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
public class WithInnerClassTransformation implements ASTTransformation {
public void visit(ASTNode[] nodes, SourceUnit source) {
ClassNode outer = nodes[1];
String name = nodes[0].getMember('name').text;
def innerClassNode = new InnerClassNode(
outer,
"$outer.name\$$name",
ClassNode.ACC_PUBLIC,
new ClassNode(GroovyObject),
);
def compilerConfiguration = source.getAST().getUnit().config;
def compilationUnit = new CompilationUnit(compilerConfiguration);
compilationUnit.addClassNode(innerClassNode);
compilationUnit.compile();
}
}
以上简单用法:
@WithInnerClass(name = "InnerClass")
public class OuterClass {}
使用以下脚本,我确认可以通过系统类加载器访问生成的类。
def classLoader = ClassLoader.getSystemClassLoader()
Class inner = classLoader.loadClass("OuterClass\$InnerClass")
assert inner.simpleName == "InnerClass"
assert OuterClass.declaredClasses.toList().contains(inner)
println OuterClass.InnerClass.class
但是,当我尝试显式使用该类时,收到此错误消息:
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: InnerClass for class: OuterClass
at groovy.lang.MetaClassImpl.invokeStaticMissingProperty(MetaClassImpl.java:997)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1852)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1828)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3735)
at org.codehaus.groovy.runtime.callsite.ClassMetaClassGetPropertySite.getProperty(ClassMetaClassGetPropertySite.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:291)
at main.run(main.groovy:5)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1208)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1017)
at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:914)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:897)
at org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:407)
at org.codehaus.groovy.runtime.InvokerHelper$runScript.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:128)
at main.main(main.groovy)
此外,尝试使用导入会导致此错误:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
main.groovy: 1: unable to resolve class OuterClass.InnerClass
@ line 1, column 1.
import OuterClass.InnerClass
^
答案 0 :(得分:0)
看来,为了明确使用生成的类,需要额外的几轮编译。要使此代码正确运行(甚至能够导入生成的类),请分3步进行编译。
groovyc WithInnerClass.groovy WithInnerClassTransformation.groovy
groovyc OuterClass.groovy
groovyc main.groovy
WithInnerClass.groovy和WithInnerClassTransformation.groovy必须与OuterClass.groovy分开编译,才能生成OuterClass $ InnerClass.class文件。
此外,OuterClass.groovy必须与main.groovy分开编译。虽然在这种情况下OuterClass $ InnerClass.class将出现在类路径中,但由于我不清楚的原因,这不足以能够在main.groovy中显式使用InnerClass。单独编译main.groovy,groovyc能够提取“真正的”类文件。