一、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再试一下导包