一、AbstractProcessor
AbstractProcessor是抽象处理器,开发apt时都必须实现这个类来生成java文件,实现这个类后叫做注解处理器,他是在编译时搜索注解并给与相应处理并生成相应的代码。对个注解的处理,是重点,重要在它能够获取所注解的元素的信息。不过这次只重点介绍AbstractProcessor,不把重心放在代码生成上。以后做apt时必定需要这个类。
首先说一下我们要实现这个类的函数(AbstractProcessor)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
@Override public synchronized void init(ProcessingEnvironment processingEnvironment) { super.init(processingEnvironment); //初始化我们需要的基础工具 mTypeUtils = processingEnv.getTypeUtils(); mElementUtils = processingEnv.getElementUtils(); mFiler = processingEnv.getFiler(); mMessager = processingEnv.getMessager(); } //在这个类获取很多工具类为了方便获取所注解的类的信息,工具类的具体使用后面说明 @Override public boolean process(Setset, RoundEnvironment roundEnvironment) { Setelements = roundEnvironment.getElementsAnnotatedWith(ZyaoAnnotation.class); // 遍历所有被注解了@Factory的元素 for (Element annotatedElement : elements) { // 检查被注解为@Factory的元素是否是一个类 if (annotatedElement.getKind() != ElementKind.CLASS) { error(annotatedElement, "Only classes can be annotated with @%s", ZyaoAnnotation.class.getSimpleName()); return true; // 退出处理 } analysisAnnotated(annotatedElement); } return true; } //遍历被注解的元素并给与相应处理 @Override public Set getSupportedAnnotationTypes() { //支持的注解 Set annotations = new LinkedHashSet<>(); annotations.add(ZyaoAnnotation.class.getCanonicalName()); return annotations; } //指定注解类型 @Override public SourceVersion getSupportedSourceVersion() { //支持的java版本 return SourceVersion.RELEASE_7; } //指定编译这个类使用的Java版本 |
二、apt环境配置
首先新建一个project,然后再新建两个JavaLibrary的 module,名字为annotation、compiler 其中compiler需要添加依赖
1 2 |
compile 'com.google.auto.service:auto-service:1.0-rc2' compile 'com.squareup:javapoet:1.7.0' |
app这个主module引入这个两个module
1 2 |
compile project(':annotation') annotationProcessor project(':compiler') |
annotation负责注解代码,compiler负责将生成代码 注解负责向依附的类添加运行代码,并且还能够将依附的类的信息传给compiler,使compiler能够生成符合依附的类的代码,这个代码给与注解,让注解在依附的类里运行代码。 因为包名不好判断,代码我就连包名也贴出来
1.这是annotaion的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by ZTH on 2018/1/22. */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS) public @interface ZyaoAnnotation { String name() default "undefined"; String text() default ""; } |
2.这是compiler的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
import com.example.annotation.ZyaoAnnotation; import com.google.auto.service.AutoService; import java.io.IOException; import java.io.Writer; import java.util.LinkedHashSet; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; @AutoService(Processor.class) public class MyProcessor extends AbstractProcessor { private Types mTypeUtils; private Elements mElementUtils; private Filer mFiler; private Messager mMessager; @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { super.init(processingEnvironment); //初始化我们需要的基础工具 mTypeUtils = processingEnv.getTypeUtils(); mElementUtils = processingEnv.getElementUtils(); mFiler = processingEnv.getFiler(); mMessager = processingEnv.getMessager(); } @Override public SourceVersion getSupportedSourceVersion() { //支持的java版本 return SourceVersion.RELEASE_7; } @Override public Set<string> getSupportedAnnotationTypes() { //支持的注解 Set<string> annotations = new LinkedHashSet<>(); annotations.add(ZyaoAnnotation.class.getCanonicalName()); return annotations; } @Override public boolean process(Set<!--? extends TypeElement--> set, RoundEnvironment roundEnvironment) { if (set == null || set.isEmpty()) { return true; } Set<!--? extends Element--> elements = roundEnvironment.getElementsAnnotatedWith(ZyaoAnnotation.class); if (elements == null || elements.isEmpty()) { return true; } // 遍历所有被注解了@Factory的元素 for (Element annotatedElement : elements) { // 检查被注解为@Factory的元素是否是一个类 if (annotatedElement.getKind() != ElementKind.CLASS) { return true; // 退出处理 } analysisAnnotated(annotatedElement); } return true; } private static final String SUFFIX = "$$ZYAO"; private void analysisAnnotated(Element classElement) { ZyaoAnnotation annotation = classElement.getAnnotation(ZyaoAnnotation.class); String name = annotation.name(); String text = annotation.text(); // TypeElement superClassName = mElementUtils.getTypeElement(name); String newClassName = name + SUFFIX; StringBuilder builder = new StringBuilder() .append("package com.example.zth.myapplication;\n\n") .append("public class ") .append(newClassName) .append(" {\n\n") // open class .append("\tpublic String getMessage() {\n") // open method .append("\t\treturn \""); // this is appending to the return statement builder.append(text).append(name).append(" !\\n"); builder.append("\";\n") // end return .append("\t}\n") // close method .append("}\n"); // close class try { // write the file JavaFileObject source = mFiler.createSourceFile("com.example.zth.myapplication."+newClassName); Writer writer = source.openWriter(); writer.write(builder.toString()); writer.flush(); writer.close(); } catch (IOException e) { // Note: calling e.printStackTrace() will print IO errors // that occur from the file already existing after its first run, this is normal } } } } |
3.这是app的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@ZyaoAnnotation( name = "Zyao", text = "Hello !!! Welcome " ) public class MainActivity extends Activity { TextView tv1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv1 = (TextView)findViewById(R.id.tv1); tv1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Zyao$$ZYAO zyao$$ZYAO = new Zyao$$ZYAO(); String message = zyao$$ZYAO.getMessage(); tv1.setText(message); } }); } } } |
如果MainActivity说没有什么类,那就先make project再试一下导包