Android Annotation Processor从不同模块访问Annotated类

时间:2017-03-27 07:31:46

标签: java android annotations android-gradle annotation-processing

我正在拥有一个包含2个模块的Android Studio项目:A和B.(我这里不包括Annotation Processor和Annotations模块)

B取决于A。

B是Android库模块,A是简单的Java库模块。我在模块B上也有一个注释处理器。

我面临的问题是:

我想根据放在两个模块 - A和B中的带注释文件生成一些代码。问题来自Annotation Processor的工作方式 - 只有源代码文件* .java - 没有编译* .class的。不幸的是,在编译B期间,Annotation Processor无法访问来自A ...

的源文件

我唯一可以想到的是一种解决方案,即使是一种丑陋的解决方案,也包括带有来自模块A的带注释类的文件夹作为模块B的源集。这样我给模块B在编译期间访问这些文件。

sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', '../module_A/src/main/java/path/to/annotated/classes/folder']
        }
    }
}

解决了这个问题 - 现在Annotation Processor可以访问两个模块中的所有带注释的类,但是......

不幸的是,它引入了另一个问题......来自模块A的那些带注释的类现在被编译两次。它们包含在模块A的JAR文件和模块B的AAR文件中。

问题1:还有另一种方法可以从B上运行的注释处理器访问模块A的源文件吗? (从我能找到的,答案是否定的,但检查......)

问题2:如何从模块B的AAR最终包中排除那些已编译的文件(重复的文件)?

问题3:也许......这是绝对错误的做法?有什么建议吗?

提前致谢!

1 个答案:

答案 0 :(得分:1)

Nop,仅使用java.lang.model API无法达到您想要的效果。至少没有一些额外的技巧。

问题不在于binary-vs-source。注释处理器可以使用Elements#getTypeElement来内省编译的类以及源定义的类:

Elements elementUtil = processingEnvironment.getElementUtils();
TypeElement integerClass = elementUtil.getTypeElement("java.lang.Integer");
TypeElement myClass = elementUtil.getTypeElement("currently.compiled.Class");

但是你仍然需要在编译类路径上使用类来观察它,并且该类必须正在编译为getElementsAnnotatedWith可见。

您可以使用FastClasspathScanner之类的工具解决以后的限制:它将使用它自己的机制在编译的字节码中查找注释,并将它们与编译过程分开报告给您。但是您无法解决类路径问题:如果您在编译类路径中没有某些依赖项,则无法处理它。所以你一起编译模块 - 通过将它们合并为一个(如你所做的那样)或通过声明一个依赖于另一个模块。在以后的情况下,您可能无法使用getElementsAnnotatedWith,但getTypeElement和FastClasspathScanner将起作用。