当前位置 博文首页 > 用心编码:Java 编程思想--注解(二)
1.采用 apt 工具构建注解处理器
(1)申明注解
/**
* 申明注解
* function : 将一个类中的 public 提取出来,抽象为一个接口。
* value :作为抽象出来接口的名称
* 该接口用户类级别,在编译之前对源代码进行处理。
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ExtractInterface {
String value();
}
(2)使用注解
/**
* 使用Multiplier 注解,内部实现两个数相乘。
*/
@ExtractInterface(value = "IMultiplier")
public class Multiplier {
public int multiplier(int x, int y) {
int total = 0;
for (int i = 0; i < x; i++) {
total = add(total, y);
}
return total;
}
private int add(int x, int y) {
return x + y;
}
public static void main(String[] args) {
Multiplier m = new Multiplier();
System.out.println("11 * 16 = " + m.multiplier(11, 16));
}
}
(3)注解处理器
/**
* 注解处理器
*
* 1.首先需要加入 apt-mirror-api-0.1.jar
* 2.需要实现 AnnotationProcessor 接口
* 3.所有的工作都在 process() 方法中,在分析一个类的时候,我们用 MethodDeclaration 类以及其上的 getModifier() 方法找到 public 方法且不包括 static方法,
* 找到我们所需的方法后,就将其保存在一个 集合中,然后在一个java文件中创建接口。
*/
public class InterfaceExtractorProcessor implements AnnotationProcessor {
private final AnnotationProcessorEnvironment env;
public InterfaceExtractorProcessor(AnnotationProcessorEnvironment env) {
this.env = env;
}
private ArrayList<MethodDeclaration> interfaceMethods = new ArrayList<MethodDeclaration>();
public void process() {
for (TypeDeclaration typeDecl : env.getSpecifiedTypeDeclarations()) {
ExtractInterface annot = typeDecl.getAnnotation(ExtractInterface.class);
if (annot == null) {
break;
}
for (MethodDeclaration method : typeDecl.getMethods()) {
if (method.getModifiers().contains(Modifier.PUBLIC) && !(method.getModifiers().contains(Modifier.STATIC))) {
interfaceMethods.add(method);
}
}
if (interfaceMethods.size() > 0) {
try {
PrintWriter writer = env.getFiler().createSourceFile(annot.value());
writer.println("package " + typeDecl.getPackage().getQualifiedName() + ";");
writer.println("public interface " + annot.value() + " {");
for (MethodDeclaration method : interfaceMethods) {
writer.print(" public ");
writer.print(method.getReturnType() + " ");
writer.print(method.getSimpleName() + " (");
int i = 0;
for (ParameterDeclaration param : method.getParameters()) {
writer.print(param.getType() + " " + param.getSimpleName());
if (++i < method.getParameters().size()) {
writer.print(", ");
}
writer.print(");");
}
writer.println("}");
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
(4)处理 “注解处理器” 的工厂
/**
* apt 工具需要一个工厂类来为其指明正确的处理器,然后才能调用处理器上的 process()方法。
*
*/
public class InterfaceExtractorProcessorFactory implements AnnotationProcessorFactory {
public Collection<String> supportedOptions() {
return Collections.emptySet();
}
public Collection<String> supportedAnnotationTypes() {
return Collections.singleton("com.daxiong.annotation.base.demo03.ExtractInterface");
}
public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> set, AnnotationProcessorEnvironment annotationProcessorEnvironment) {
return new InterfaceExtractorProcessor(annotationProcessorEnvironment);
}
}
2.总结
(1)jdk自带的注解,处理文档,覆盖等。
(2)java 元注解,用于自定义注解之上,构建用户自己需要的注解。
如何构建
对编译后文件:java 反射机制。
对编译前资源文件:jdk apt 构建工具。
两种方式的区别,优缺点
3.模拟 Junit 的 @Test
cs