如何使用 Java 1.6 注解处理来执行编译时编织?
我创建了一个注释,将其应用到 DTO 并编写了一个 Java 1.6 风格的注释处理器。我可以看到如何让annotationProcessor编写一个新的源文件,这不是我想要做的,我看不到或找出如何让它修改现有的类(理想情况下只是修改字节代码)。修改实际上相当简单,我希望处理器做的就是插入一个新的 getter 和 setter,其中名称来自正在处理的注释的值。
我的注释处理器看起来像这样;
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes({ "com.kn.salog.annotation.AggregateField" })
public class SalogDTOAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
//do some stuff
}
}
I have created an annotation, applied it to a DTO and written a Java 1.6 style annotationProcessor. I can see how to have the annotationProcessor write a new source file, which isn't what I want to do, I cannot see or find out how to have it modify the existing class (ideally just modify the byte code). The modification is actually fairly trivial, all I want the processor to do is to insert a new getter and setter where the name comes from the value of the annotation being processed.
My annotation processor looks like this;
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes({ "com.kn.salog.annotation.AggregateField" })
public class SalogDTOAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
//do some stuff
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您正在寻找“Instrumentation”,这就是 AspectJ 等框架所做的事情。在这种情况下,您必须在命令行中使用“-agent”选项指定一个 jar,然后才能过滤所有加载的类。在此过滤步骤中,您可以检查注释,并在字节码加载到虚拟机中之前对其进行修改。用于进行实际字节码修改的库包括“asm”,可能还有高级包装器“cglib”和“javassist”。您甚至可以预编译您的类以生成必须由您检测的类列表,以使开始时的过滤速度更快一些。
有关详细信息,请参阅 java.lang.instrumentation。
You are looking for "Instrumentation", which is what frameworks like AspectJ do. In this case you have to specify a jar in the command line with the "-agent" option, and then have the possibility to filter all loaded classes. During this filter step you can check for annotations, and modify the bytecode before it gets loaded in the virtual machine. Libraries for doing the actual bytecode modification include "asm", and maybe the highlevel wrappers "cglib" and "javassist". You could even precompile your classes to generate a list of classes which have to be instrumented by you, to make filtering in the beginning a bit faster.
See java.lang.instrumentation for more info.
根据设计,注释处理工具不允许直接修改正在处理的源代码。但是,可以生成正在处理的类型的子类或正在处理的类型的超类。通过一些规划,这确实允许修改相关类型的一些效果。我写了一个例子来说明如何将它们结合在一起;有关更详细的说明,请参阅此博客文章一些示例代码。
By design, the annotation processing facility does not allow direct modification of the source code being processed. However, one can generate subclasses of the type being processed or the superclass of the type being processed. With some planning, this does allow some of the effect of modifying the type in question. I've written up an example of how this can fit together; see this blog entry for a more detailed explanation and some sample code.
您必须使用内部编译器的类 - 一些灵感:
但这是边缘政策。您的程序只能在 Sun/OpenJDK 上编译,并且在未来版本中可能会出现问题(内部 API 可能会更改)。尽管一旦编译,它就是标准字节码并且可以在任何地方运行。
BTW:如果你想在 Eclipse 中使用它,你应该为它添加一些特殊的支持,因为 Eclipse 使用非标准编译器。您的设计应该更复杂,并且应该为处理器添加一定程度的抽象 - 就像 Lombok 所做的那样。
You have to use internal compiler's classes – some inspiration:
But it is brinkmanship. Your program will compile only on Sun/OpenJDK and there can be problems in future versions (internal API can change). Although once compiled, it is standard bytecode and will run everywhere.
BTW: if you want use it in Eclipse, you should add some special support for it because Eclipse uses non-standard compiler. Your design should be more complex and you should add a level of abstraction to your processor – like Lombok does.
为此,您必须扩展
javac
编译器,这意味着构建您的程序不会像常规应用程序那样可移植。请参阅http://weblogs.java.net/blog/cayhorstmann /archive/2006/06/say_no_to_prope.html 了解有关某人如何实现这一目标的更多详细信息。You have to extend the
javac
compiler for this, which means building your program won't be as portable as a regular application. See http://weblogs.java.net/blog/cayhorstmann/archive/2006/06/say_no_to_prope.html for more details on how someone achieved this.