apt应用解析

    技术2022-05-11  61

    读了网上广为流传的annotation高级应用,发现其中的apt应用有点让人难以理解,   于是又去读   http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html ,   还是很难理解,annotation高级应用基本上成了sun这片文章的翻译,做了一把实验,   总结了以下,终于有点明白他的作用了。   文章上说,使用APT主要目的是简化开发者的工作量,因为APT可以在编译程序源代码   的同时,生成一些附属文件(比如源文件、类文件、程序发布描述文字等),这些附属   文件的内容也都是与源代码相关的。我觉得这其实主要是annotation的功劳,   apt只是annotation处理的一种框架,可以省去很多自己处理annotation   时需要写的代码。   以下通过改造的实例来解释apt的使用。(使用时要把jdk5.0lib目录里的tools.jar加到classpath中 这个在JRE里没有。   Decription1.java   package ano.apt; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;   @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented   public @interface Description1 {   String value(); }   Description2.java   package ano.apt; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;   @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented   public @interface Description2 {   String value(); }     Name.java   package ano.apt; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;    @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME)    @Documented public @interface Name {   String originate();   String community(); }   BraveNoEnemy.java   package ano.apt;   @Description1("description1")   @Description2("description2")   public class BraveNoEnemy {    @Name(originate = "创始人:cz_hyf1", community = "csdn1")    public String getName() {      return "name1";     }    @Name(originate = "创始人:cz_hyf2", community = "csdn2")    public String getName2() {       return "name2";    } } BraveNoEnemyDeclarationVisitor.java package ano.apt; import com.sun.mirror.util.*; import com.sun.mirror.declaration.*; /**  * 定义Review annotation声明访问者  * @author cz_hyf  **/    public class BraveNoEnemyDeclarationVisitor extends SimpleDeclarationVisitor{     /**   * 定义访问类声明的方法:打印类声明的全名   * @param cd 类声明对象   */     public void visitClassDeclaration(ClassDeclaration cd){   System.out.println("获取Class声明:"+cd.getQualifiedName());  }    public void visitDeclaration(ClassDeclaration cd){   System.out.println("获取Class声明:"+cd.getQualifiedName());  }    public void visitAnnotationTypeDeclaration(AnnotationTypeDeclaration atd){   System.out.println("获取Annotation类型声明:"+atd.getSimpleName());  }    public void visitAnnotationTypeElementDeclaration(AnnotationTypeElementDeclaration aed){   System.out.println("获取Annotation类型元素声明:"+aed.getSimpleName());  } } ProcessorFactory.java   package ano.apt;   import java.util.Collection; import java.util.Set; import java.util.Arrays; import com.sun.mirror.apt.*; import com.sun.mirror.declaration.AnnotationTypeDeclaration; import com.sun.mirror.apt.AnnotationProcessorEnvironment; import static java.util.Collections.unmodifiableCollection; import static java.util.Collections.emptySet;   /**  * 生成ReviewProcessor的工厂类  *  * @author cz_hyf  */ public class ProcessorFactory implements AnnotationProcessorFactory {    /**   * 获得针对某个(些)类型声明定义的Processor   *   * @param atds   *            类型声明集合   * @param env   *            processor环境   */    public AnnotationProcessor getProcessorFor(    Set<AnnotationTypeDeclaration> atds,    AnnotationProcessorEnvironment env) {    return new DesAnnotationProcessor(env);  }    /**   * 定义processor所支持的annotation类型   *   * @return processor所支持的annotation类型的集合   */    public Collection<String> supportedAnnotationTypes() {   // “*”表示支持所有的annotation类型   // 当然也可以修改为“foo.bar.*”、“foo.bar.Baz”,来对所支持的类型进行修饰   return unmodifiableCollection(Arrays.asList("*"));  }    /**   * 定义processor支持的选项   *   * @return processor支持选项的集合   */    public Collection<String> supportedOptions() {   // 返回空集合   return emptySet();  }    public static void main(String[] argv) {   System.out.println("ok");  } }   AtypeVisitor.java   package ano.apt;   import com.sun.mirror.type.AnnotationType; import com.sun.mirror.util.*; import com.sun.mirror.declaration.*;   /**     * 定义Review annotation声明访问者     *      * @author cz_hyf     */   public class AtypeVisitor extends SimpleTypeVisitor {    /**   * 定义访问类声明的方法:打印类声明的全名   *   * @param cd   * 类声明对象   */    public void visitAnnotationType(AnnotationType t) {   System.out.println("获取AnnotationType声明:"     + t.getDeclaration().getQualifiedName());  } }   DesAnnotationProcessor.java   package ano.apt;   import java.util.Collection; import java.util.Iterator;   import com.sun.mirror.apt.AnnotationProcessor; import com.sun.mirror.apt.AnnotationProcessorEnvironment; import com.sun.mirror.declaration.AnnotationMirror; import com.sun.mirror.declaration.TypeDeclaration; import com.sun.mirror.type.AnnotationType; import com.sun.mirror.util.DeclarationVisitors; import com.sun.mirror.util.DeclarationVisitor; import com.sun.mirror.util.TypeVisitor;   /**  * 定义Review annotation的Processor  *  * @author cz_hyf  */   public class DesAnnotationProcessor implements AnnotationProcessor {  // Processor所工作的环境  AnnotationProcessorEnvironment env = null;    /**   * 构造方法   *   * @param env   *            传入processor环境   */    public DesAnnotationProcessor(AnnotationProcessorEnvironment env) {   this.env = env;  }    /**   * 处理方法:查询processor环境中的类型声明,   */    public void process() {     // 查询processor环境中的类型声明   System.out.println("begin process/n");   for (TypeDeclaration type : env.getSpecifiedTypeDeclarations()) {    // 返回对类进行扫描、访问其声明时使用的DeclarationVisitor    // 传入参数:new ReviewDeclarationVisitor(),为扫描开始前进行的对类声明的处理    // DeclarationVisitors.NO_OP,表示在扫描完成时进行的对类声明不做任何处理    DeclarationVisitor visitor = DeclarationVisitors      .getDeclarationScanner(        new BraveNoEnemyDeclarationVisitor(),        DeclarationVisitors.NO_OP);    Collection<AnnotationMirror> annotationmirrorc = type      .getAnnotationMirrors();    for (AnnotationMirror amirror : annotationmirrorc) {     // 应用DeclarationVisitor到类型     AnnotationType typemirror = amirror.getAnnotationType();     typemirror.accept(new AtypeVisitor());    }   }   System.out.println("end process/n");    } }   运行的bat文件   runapt.bat   rem 项目根目录   set PROJECT_ROOT=d:/annoproject/   rem 包目录路径   set PACKAGEPATH=ano.apt   rem 运行根路径   set RUN_ROOT=%PROJECT_ROOT%   rem 源文件所在目录路径   set SRC_ROOT=%PROJECT_ROOT%   rem 设置Classpath   set CLASSPATH=.;%JAVA_HOME%;%JAVA_HOME%/lib/tools.jar;%RUN_ROOT%   apt -encoding utf8 -factory ano.apt.ProcessorFactory  ./ano/apt/BraveNoEnemy.java   在dos目录下运行runapt,由于apt命令没有跟-nocompile参数,将会编译所有的java文件。   编译完后运行步骤如下:   (1)找到ProcessFacotry,因为方法supportedAnnotationTypes() 返回   unmodifiableCollection(Arrays.asList("*"));所以其要处理的Annotation为所有出现的   Annotation,由于runapt.bat中包含的要处理的文件为BraveNoEnemy.java,其中包含的所有   annotation为Name、Description1、Description2为这三个要处理的annotation返回一个   Process即DesAnnotationProcessor。   (2) 运行DesAnnotationProcessor的Process方法。      由于目前要运行的类型只有一个(由于只处理BraveNoEnemy文件,它只包含一种   type,即ano.apt.BraveNoEnemy),所以第一层process方法的第一层循环为处理type.   由于type(BraveNoEnemy)包含了Description1和Description2,所以第二重循环为   处理Description的访问。  

    最新回复(0)