Java 6 - 注释处理器和代码添加

Den*_*cay 15 java osgi bytecode properties code-injection

我写了一个包含属性元数据的自定义注释,并且AnnotationProcessor:

@SupportedAnnotationTypes({"<package>.Property"})
public class PropertyProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        // Get messager object
        Messager messager = processingEnv.getMessager();
        // Iterate through the annotations
        for(TypeElement typeElement : annotations) {
            // Iterate through the annotated elements
            for(Element element : roundEnv.getElementsAnnotatedWith(typeElement)) {
                // Get Property annotation
                Property property = element.getAnnotation(Property.class);

            }
        }
        return false;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个问题,我之前使用过Javassist,但它依赖于类加载器,我认为它不适合OSGi应用程序.我想在Property编译带有注释的类时更改生成的字节码.

Tri*_*Cyr 6

你试过Google Guice吗?

Google Guice允许您通过拦截方法进行面向方面编程.如果这就是你需要做的全部,你可以实现一个MethodInterceptor,它允许你在运行时覆盖方法.它非常适合隔离交叉问题.

例如,假设您想要阻止某些方法在周末执行,您可以这样注释它们:

@Property
public class SomeClass {
    public Receipt doSometing() {
        // Do something
    }
}
Run Code Online (Sandbox Code Playgroud)

定义一个MethodInterceptor:

public class PropertyInterceptor implements MethodInterceptor {
  public Object invoke(MethodInvocation invocation) throws Throwable {
    // For example prevent the classes annotated with @Property
    // from being called on weekends
    Calendar today = new GregorianCalendar();
    if (today.getDisplayName(DAY_OF_WEEK, LONG, ENGLISH).startsWith("S")) {
      throw new IllegalStateException(
          invocation.getMethod().getName() + " not allowed on weekends!");
    }
    return invocation.proceed();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后将拦截器绑定到注释:

public class PropertyModule extends AbstractModule {
  protected void configure() {
        PropertyInterceptor propertyInterceptor = new PropertyInterceptor();        
        bindInterceptor(Matchers.annotatedWith(Property.class), 
        Matchers.any(), propertyInterceptor);
  }
}
Run Code Online (Sandbox Code Playgroud)


Sea*_*oyd 5

简短的回答是:您不应该在注释处理期间更改源代码.

我最近遇到的情况是答案不理想(见这个问题).我的解决方案是使用内部javac api以编程方式添加我需要的代码.有关详细信息,请参阅我对自己问题的回答.

我把灵感,这从项目龙目岛,与他们的源代码起步,扔掉一切,我也没必要.我不认为你会找到一个更好的起点.

顺便说一下,Javassist可能无济于事,因为你正在处理一个源代码树,而不是字节代码.如果你想使用一个字节码操作库,你可以做,要么当加载的类,但不能标注在加工过程中,因为这是一个编译预处理步骤编译或动态静态后.