12 java reflection annotations
如何更改Java中的方法?
我的意思是,我正在尝试使用注释来制作以下代码
@Anno1(Argument = "Option1")
public class TestClass
{
@Anno2
public void test()
{
}
}
Run Code Online (Sandbox Code Playgroud)
成
public class TestClass
{
private static StaticReference z;
public void test()
{
z.invokeToAll();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我想要做的一个非常简单的例子.Anno1
将有许多可能的组合,但到目前为止这不是我的问题.我的问题是如何向方法添加代码test()
如果可能的话,我正在寻找更通用的解决方案.例如.一种在方法中添加各种代码的方法(不仅仅是一种方法.invokeToAll()
)
到目前为止我正在使用import javax.annotation.processing.*;
,我有以下代码,但我不知道如何从那里继续
private void processMethodAnnotations(RoundEnvironment env)
{
for (Element e : env.getElementsAnnotatedWith(Anno2.class))
{
//If it is a valid annotation over a method
if (e.getKind() == ElementKind.METHOD)
{
//What to do here :S
}else
{
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,"Not a method!", e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我找到了一些关于Java Reflection的内容,但我没有找到任何来源来帮助我完成我正在做的事情.
显然我extends AbstractProcessor
在我的代码中
我找到了这个教程(http://www.zdnetasia.com/writing-and-processing-custom-annotations-part-3-39362483.htm)但这涉及创建一个新类,而不仅仅是更改方法.并且javax.lang.model.elements
不提供任何编辑该元素的方法(在我的例子中代表一个方法).
我希望我的问题清楚,并符合规则.如果没有请评论,我会澄清.谢谢.
Max*_*xym 12
从维基百科来看,注释处理是错误的方法:
编译Java源代码时,注释可以由称为注释处理器的编译器插件处理.处理器可以生成信息性消息或创建其他Java源文件或资源,这些文件或资源又可以编译和处理,但注释处理器不能修改带注释的代码本身.
人们建议你正确的方式 - AOP.具体来说,您可以使用AspectJ."快速结果"的方式是(如果你使用Eclipse):
1)安装AJDT(AspectJ开发工具)
2)创建AspectJ项目并在其中添加类和注释
3)创建方面:
public aspect Processor {
private StaticReference z;
pointcut generic()
// intercept execution of method named test, annotated with @Anno1
// from any class type, annotated with @Anno2
: execution(@Anno2 * (@Anno1 *).test())
// method takes no arguments
&& args ();
// here you have write what you want method actually does
void around () : generic() {
z.invokeToAll();
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以执行一个测试,你会发现它有效;)AJDT会自动为你编译代码,所以不需要做任何手工工作,希望这就是你所谓的"魔法";)
更新:
如果test()方法中的代码依赖于Anno1注释值,那么在内部方面,您可以获得以这种方式执行的类注释:
void around () : generic() {
Annotation[] classAnnotations = thisJoinPoint.getThis().getClass().getAnnotations();
String ArgumentValue = null;
for ( Annotation annotation : classAnnotations ) {
if ( annotation instanceof Anno1 ) {
ArgumentValue = ((Anno1) annotation).Argument();
break;
}
}
if ( ArgumentValue != null && ArgumentValue.equals("Option1")) {
z.invokeToAll();
}
}
Run Code Online (Sandbox Code Playgroud)
其中thisJoinPoint是一个特殊的引用变量.
UPDATE2:
如果你想添加System.out.println( this )
你的方面,你需要在那里写System.out.println( thisJoinPoint.getThis() )
,只是测试,它的工作原理.thisJoinPoint.getThis()
给你回复"这个"但不完全是; 实际上这是对象变量,如果你想获得任何属性,你需要强制转换或使用反射.并且thisJoinPoint.getThis()
不提供私人财产的访问权限.
好吧,现在好像你的问题得到了解答,但是如果我错过了什么,或者你用这种方式得到了额外的问题/问题 - 随便问一下;)
尽管有一个警告:依赖私有编译器 API,但完全有可能按照您的要求执行操作。听起来很可怕,但事实并非如此(编译器实现往往是稳定的)。
有一篇论文解释了这个过程:The Hacker's Guide to Javac。
值得注意的是,Project Lombok 使用它来提供自动 getter/setter 生成(除其他外)。在下面的文章解释了它是怎么做的,基本上重新迭代说什么了上述文件。