[编织消息框架][JAVA核心技术]动态代理应用4-annotationProcessor

基础部份:

接下来讲编译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,后面会有详细介绍

原文地址:https://www.cnblogs.com/solq111/p/6669713.html