基础部份:
接下来讲编译JAVA时,生成自定义class
我们用 javax.annotation.processing.AbstractProcessor 来处理
public abstract class AbstractProcessor implements Processor { protected ProcessingEnvironment processingEnv; public Set<String> getSupportedOptions() { SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class); if (so == null) return Collections.emptySet(); else return arrayToSet(so.value()); } public Set<String> getSupportedAnnotationTypes() { SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class); if (sat == null) { //省略 return Collections.emptySet(); } else return arrayToSet(sat.value()); } public SourceVersion getSupportedSourceVersion() { SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class); SourceVersion sv = null; if (ssv == null) { sv = SourceVersion.RELEASE_6; //省略 } else sv = ssv.value(); return sv; } }
继承AbstractProcessor 需要关心几个地方
1.@SupportedSourceVersion 支持java源码版本,扫描项目java文件过滤
2.@SupportedAnnotationTypes 过滤的 Annotation class
3.属性ProcessingEnvironment
其中有个概念Element包含 class、method、field等信息
我们只关心以下几种类型:
1.TypeElement 对象包含class 信息
2.VariableElement 对象包含 field, constant, method or constructor parameter, local variable 等信息
其中通过getEnclosingElement 能获取到目标TypeElement
实现部份:
由于 process(Set<? extends TypeElement> annotations, RoundEnvironment env) annotations参数只是 @SupportedAnnotationTypes 上绑定的anno class 没有提取到相关的处理类
可以通过env.getRootElements()获取全部的类,或内部带过滤的方法 env.getElementsAnnotatedWith
@SupportedAnnotationTypes({ "com.eyu.TestAnnotation" }) @SupportedSourceVersion(SourceVersion.RELEASE_7) public class MyProcessor extends AbstractProcessor { /*** * {@link ElementFilter} */ public static final Set<ElementKind> CONSTRUCTOR_KIND = Collections.unmodifiableSet(EnumSet.of(ElementKind.CONSTRUCTOR)); public static final Set<ElementKind> FIELD_KINDS = Collections.unmodifiableSet(EnumSet.of(ElementKind.FIELD, ElementKind.ENUM_CONSTANT)); public static final Set<ElementKind> METHOD_KIND = Collections.unmodifiableSet(EnumSet.of(ElementKind.METHOD)); public static final Set<ElementKind> PACKAGE_KIND = Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE)); public static final Set<ElementKind> TYPE_KINDS = Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS, ElementKind.ENUM, ElementKind.INTERFACE, ElementKind.ANNOTATION_TYPE)); @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) { Set<? extends Element> elememts = env.getElementsAnnotatedWith(com.eyu.TestAnnotation.class); Set<Class<?>> clz = new HashSet<>(); for (Element ele : elememts) { String key = null; if (TYPE_KINDS.contains(ele.getKind())) { TypeElement classElement = (TypeElement) ele; key = classElement.getQualifiedName().toString(); } else if (FIELD_KINDS.contains(ele.getKind()) || METHOD_KIND.contains(ele.getKind())) { VariableElement varELe = (VariableElement) ele; TypeElement enclosingElement = (TypeElement) varELe.getEnclosingElement(); key = enclosingElement.getQualifiedName().toString(); } if (key == null) { continue; } try { clz.add(Class.forName(key)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } for (Class<?> key : clz) { System.err.println(key); } return false; }
}
执行部份:
执行自定义AbstractProcessor有两种方式
1.在maven项目 pom.xml 添加
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> <annotationProcessors> <annotationProcessor>com.eyu.MyProcessor</annotationProcessor> </annotationProcessors> <debug>true</debug> <optimize>true</optimize> <source>1.8</source> <target>1.8</target> <compilerArguments> <AaddGeneratedAnnotation>true</AaddGeneratedAnnotation> <Adebug>true</Adebug> </compilerArguments> </configuration> </plugin>
2.在resource/META-INF/services 新建 javax.annotation.processing.Processor 文件
内容为自定义处理类 com.eyu.MyProcessor
然后创建maven build 配置 Goals输入install即可 在实际测试中只有删除/添加java文件才触发一次执行
细心的读者会发者,上篇没有写如何发送消息,这篇没有如何写生成class,后面会有详细介绍