读了网上广为流传的annotation高级应用,发现其中的apt应用有点让人难以理解,
于是又去读
还是很难理解,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.*;
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());
}
}
* 定义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类型的集合
*/
* 定义processor所支持的annotation类型
*
* @return processor所支持的annotation类型的集合
*/
public Collection<String> supportedAnnotationTypes() {
// “*”表示支持所有的annotation类型
// 当然也可以修改为“foo.bar.*”、“foo.bar.Baz”,来对所支持的类型进行修饰
return unmodifiableCollection(Arrays.asList("*"));
}
/**
* 定义processor支持的选项
*
* @return processor支持选项的集合
*/
* 定义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环境
*/
* 构造方法
*
* @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的访问。