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

我写了一个自定义注释,其中包含属性的元数据和: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;
    }

}

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


答案 1

你试过谷歌吉思吗

Google Guice允许您通过拦截方法来进行一些面向方面的编程。如果这就是您需要执行的所有操作,则可以实现一个 MethodInterceptor,该方法接收器将允许您在运行时重写方法。对于隔离跨领域问题来说,这真的很整洁。

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

@Property
public class SomeClass {
    public Receipt doSometing() {
        // Do something
    }
}

定义方法接收器:

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();
  }
}

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

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

答案 2

简短的回答是:在注释处理过程中,您不应该更改源代码。

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

我从龙目岛项目(Project Lombok)中汲取了灵感,从他们的源代码开始,扔掉了我不需要的一切。我不认为你会找到一个更好的起点。

顺便说一句,Javassist可能无济于事,因为你正在处理源树,而不是字节码。如果要使用字节代码操作库,可以在编译后静态执行此操作,也可以在加载类时动态执行此操作,但在注释处理期间则不然,因为这是预编译步骤。