标签:
在开始之前,我们首先申明一个非常重要的问题:我们并不讨论那些在运行时(Runtime)通过反射机制运行处理的注解,而是讨论在编译时(Compile time)处理的注解。注解处理器是一个在javac中的,用来编译时扫描和处理的注解的工具。可以为特定的注解,注册自己的注解处理器。
一个注解的注解处理器,以Java代码(或者编译过的字节码)作为输入,生成文件(通常是.java文件)作为输出。可以生成Java代码,这些生成的Java代码是在生成的.java文件中,所以不能修改已经存在的Java类,例如向已有的类中添加方法。这些生成的Java文件,会同其他普通的手动编写的Java源代码一样被javac编译。
虚处理器AbstractProcessor
我们首先看一下处理器的API。每一个处理器都是继承于AbstractProcessor,如下所示:
public class MyProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { } }
举一个简单例子
自动生成一个bean的结构文件
把 public class Student { public String stu_name; public String stu_id; public int stu_age; } 转换为 {class:"com.robert.processor.Student", fields: { stu_name:"java.lang.String", stu_id:"java.lang.String", stu_age:"java.lang.Integer" } }首先声明注解
package com.robert.processor; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ ElementType.FIELD, ElementType.TYPE }) @Retention(RetentionPolicy.CLASS) public @interface Serialize { }将注解加到Student类上
定义自己的解析器
package com.robert.processor; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; public class MyProcessor extends AbstractProcessor { // 元素操作的辅助类 Elements elementUtils; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); elementUtils = processingEnv.getElementUtils(); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { // 获得被该注解声明的元素 Set<? extends Element> elememts = roundEnv.getElementsAnnotatedWith(Serialize.class); TypeElement classElement = null;// 声明类元素 List<VariableElement> fields = null;// 声明一个存放成员变量的列表 // 存放二者 Map<String, List<VariableElement>> maps = new HashMap<String, List<VariableElement>>(); // 遍历 for (Element ele : elememts) { // 判断该元素是否为类 if (ele.getKind() == ElementKind.CLASS) { classElement = (TypeElement) ele; maps.put(classElement.getQualifiedName().toString(), fields = new ArrayList<VariableElement>()); } else if (ele.getKind() == ElementKind.FIELD) // 判断该元素是否为成员变量 { VariableElement varELe = (VariableElement) ele; // 获取该元素封装类型 TypeElement enclosingElement = (TypeElement) varELe.getEnclosingElement(); // 拿到key String key = enclosingElement.getQualifiedName().toString(); fields = maps.get(key); if (fields == null) { maps.put(key, fields = new ArrayList<VariableElement>()); } fields.add(varELe); } } for (String key : maps.keySet()) { if (maps.get(key).size() == 0) { TypeElement typeElement = elementUtils.getTypeElement(key); List<? extends Element> allMembers = elementUtils.getAllMembers(typeElement); if (allMembers.size() > 0) { maps.get(key).addAll(ElementFilter.fieldsIn(allMembers)); } } } generateFile(maps); return true; } private void generateFile(Map<String, List<VariableElement>> maps) { File dir = new File(MyProcessor.class.getResource("/").getPath()); if (!dir.exists()) dir.mkdirs(); // 遍历map for (String key : maps.keySet()) { // 创建文件 File file = new File(dir, key.replaceAll("\\.", "_") + ".txt"); try { /** * 编写文件内容 */ FileWriter fw = new FileWriter(file); fw.append("{").append("class:").append("\"" + key + "\"").append(",\n "); fw.append("fields:\n {\n"); List<VariableElement> fields = maps.get(key); for (int i = 0; i < fields.size(); i++) { VariableElement field = fields.get(i); fw.append(" ").append(field.getSimpleName()).append(":") .append("\"" + field.asType().toString() + "\""); if (i < fields.size() - 1) { fw.append(","); fw.append("\n"); } } fw.append("\n }\n"); fw.append("}"); fw.flush(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override public Set<String> getSupportedAnnotationTypes() { Set<String> set = super.getSupportedAnnotationTypes(); if (set == null) { set = new HashSet<>(); } set.add("com.robert.processor.Serialize"); return set; } }
我们经常使用的ButterKnife这个框架就很好的使用了AbstractProcessor
Butter Knife 是 Android 视图字段和方法绑定,使用注解处理来生成样板代码。后面做详细说明。
欢迎扫描二维码,关注个人公众号
标签:
原文地址:http://blog.csdn.net/robertcpp/article/details/51628656