APT即为Annotation Processing Tool,它是javac的一个工具,中文意思为编译时注解处置惩罚器,APT可以用来在编译时扫描和处置惩罚注解,通过APT可以获取到注解和被注解对象的干系信息,在拿到这些信息后我们可以根据需求来自动的生成一些代码,省去了手动编写,留意,获取注解及生成代码都是在代码编译时间完成的,相比反射在运行时处置惩罚注解大大进步了步调性能。
apt是在生成.class文件之前实行,故在apt内里无法通过反射获取其他类的方法,由于反射是通过ClassLoader将Class文件加载到JVM中,在内存中举行管理。
注解处置惩罚器是运行它自己的捏造机JVM中,javac启动一个完备Java捏造机来运行注解处置惩罚器,
自界说编译注解
工程布局:
- annotation (注解和处置惩罚器生成代码干系,有的喜欢将注解和处置惩罚器分成两个包)
- app
annotation 模块
- 新建java lib 定名annotation
- build.gradle 导入依靠
dependencies { implementation 'com.squareup:javapoet:1.13.0' implementation 'com.google.auto.service:auto-service:1.0-rc6' annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'}
@Target(ElementType.TYPE)@Retention(RetentionPolicy.CLASS)public @interface NativeAnnotation { String path() default "";}
@AutoService(Processor.class)public class NativeProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { return false; }}app模块
implementation project(':annotation') annotationProcessor project(':annotation')
@NativeAnnotation(path = "111")public class MainActivity extends AppCompatActivity {}在处置惩罚器内里参加log 确认处置惩罚器有没有收效
@AutoService(Processor.class)public class NativeProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING," test NativeProcessor"); return false; }}注解表明器输出的日志在build log内里检察
从log中可以看出 表明器已收效, 在process方法中可以写自己想要的逻辑,比如生成java文件
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING," test NativeProcessor"); ClassName className = ClassName.bestGuess("com.example.Useful"); TypeSpec.Builder userTypeSpec = TypeSpec.classBuilder(className) .addModifiers(Modifier.PUBLIC); // private int id = 0; FieldSpec idFieldSpec = FieldSpec.builder(int.class, "id", Modifier.PRIVATE) .initializer("0").build(); userTypeSpec.addField(idFieldSpec); userTypeSpec.addJavadoc("解释"); JavaFile javaFile = JavaFile.builder("com.example",userTypeSpec.build()).build(); try { javaFile.writeTo(processingEnv.getFiler()); } catch (IOException e) { e.printStackTrace(); } return true; }在build目次下已生成对应文件
注解处置惩罚器核心类与函数剖析
AbstractProcessor
AbstractProcessor抽象类是实现了Processor接口,具体类变量和函数剖析如下:
- init(ProcessingEnvironment env):init()方法会被注解处置惩罚工具调用,并输入ProcessingEnviroment参数。ProcessingEnviroment提供许多有效的工具类Elements, Types和Filer。
- process(Set<? extends TypeElement> annotations, RoundEnvironment env): 这相称于每个处置惩罚器的主函数main()。你在这里写你的扫描、评估和处置惩罚注解的代码,以及生成Java文件。输入参数RoundEnviroment,可以让你查询出包罗特定注解的被注解元素。
- getSupportedAnnotationTypes(): 这里你必须指定,这个注解处置惩罚器是注册给哪个注解的。留意,它的返回值是一个字符串的集合,包罗本处置惩罚器想要处置惩罚的注解范例的合法全称。换句话说,你在这里界说你的注解处置惩罚器注册到哪些注解上。
- getSupportedSourceVersion(): 用来指定你使用的Java版本。通常这里返回SourceVersion.latestSupported()。然而,假如你有富足的来由只支持Java 6的话,你也可以返回SourceVersion.RELEASE_6。我保举你使用前者。
ProcessingEnvironment
ProcessingEnvironment对象是apt的核心工具类
获取Elements的范例
processingEnv.getElementUtils().getTypeElement(type).asType()输出调试日志
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING," test NativeProcessor");判定此元素的范例,做干系安全校验之类的
private boolean isSubtype(Element typeElement, String type) { return processingEnv.getTypeUtils().isSubtype(typeElement.asType(), processingEnv.getElementUtils().getTypeElement(type).asType());}返回用来创建类或者辅助文件的filer
JavaFile javaFile = JavaFile.builder("com.example",userTypeSpec.build()).build(); try { javaFile.writeTo(processingEnv.getFiler()); } catch (IOException e) { e.printStackTrace(); }RoundEnvironment
public interface RoundEnvironment { boolean processingOver(); //上一轮注解处置惩罚器是否产生错误 boolean errorRaised(); //返回上一轮注解处置惩罚器生成的根元素 Set<? extends Element> getRootElements(); //返回包罗指定注解范例的元素的集合 Set<? extends Element> getElementsAnnotatedWith(TypeElement a); //返回包罗指定注解范例的元素的集合 Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a);}Element
element体现一个静态的,语言级别的构件。而任何一个布局化文档都可以看作是由差异的element构成的布局体,对java源文件来说
package com.closedevice; //PackageElementpublic class Main{ //TypeElement private int x; //VariableElement private Main(){ //ExecuteableElement } private void print( //ExecuteableElement int msg ){ //VariableElement }}Element代表步调元素:包,类,方法都是一种步调元素
- VariableElement 代表一个 字段, 罗列常量, 方法或者构造方法的参数, 局部变量及 非常参数等元素
- PackageElement 代表包元素
- TypeElement 代表类或接口元素
- ExecutableElement 代码方法,构造函数,类或接口的初始化代码块等元素,也包罗注解范例元素
public interface Element extends javax.lang.model.AnnotatedConstruct { //返回一个TypeMirror元素的范例信息,包罗包名,类(或方法,或参数) //名的范例,在生成动态代码的时间,我们通常必要知道变量/方法参数的类 //型 ,以便写入正确的范例声明 TypeMirror asType(); //返回element的范例,判定是哪种element ElementKind getKind(); //获取修饰关键字,入public static final,abstract等关键字 Set<Modifier> getModifiers(); //获取名字,不带包名 Name getSimpleName(); //getEnclosedElements Element getEnclosingElement(); //返回该元素直接包罗的子元素,通常对一个PackageElement而言,它可 //以包罗TypeElement;对于一个TypeElement而言,它大概包罗属性 //VariableElement,方法ExecutableElement List<? extends Element> getEnclosedElements(); //获取该元素上的注解的范例信息 @Override List<? extends AnnotationMirror> getAnnotationMirrors(); //获取该元素上的注解 @Override <A extends Annotation> A getAnnotation(Class<A> annotationType); @Override <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType);}以上是Element的方法,同时它的子类有自己的方法
public interface ExecutableElement extends Element, Parameterizable {//用于获取方法的参数元素,每个元素是一个VariableElementList<? extends VariableElement> getParameters();//获取方法元素的返回值,返回范例TypeMirror体现TypeMirror getReturnType()}public interface VariableElement extends Element {//假如属性变量被final修饰,则可以使用该方法获取它的值Object getConstantValue();}public interface TypeElement extends Element, Parameterizable, QualifiedNameable { //获取类全限定名 Name getQualifiedName();}ElementKind
public enum ElementKind { /** A package. */ PACKAGE, // Declared types /** An enum class. */ ENUM, /** * A class not described by a more specific kind (like {@code * ENUM} or {@code RECORD}). */ CLASS, /** An annotation interface. (Formerly known as an annotation type.) */ ANNOTATION_TYPE, /** * An interface not described by a more specific kind (like * {@code ANNOTATION_TYPE}). */ INTERFACE, // Variables /** An enum constant. */ ENUM_CONSTANT, /** * A field not described by a more specific kind (like * {@code ENUM_CONSTANT}). */ FIELD, /** A parameter of a method or constructor. */ PARAMETER, /** A local variable. */ LOCAL_VARIABLE, /** A parameter of an exception handler. */ EXCEPTION_PARAMETER, // Executables /** A method. */ METHOD, /** A constructor. */ CONSTRUCTOR, /** A static initializer. */ STATIC_INIT, /** An instance initializer. */ INSTANCE_INIT, /** A type parameter. */ TYPE_PARAMETER, /** * An implementation-reserved element. This is not the element * you are looking for. */ OTHER, // Constants added since initial release /** * A resource variable. * @since 1.7 */ RESOURCE_VARIABLE, /** * A module. * @since 9 */ MODULE, /** * A record class. * @since 16 */ RECORD, /** * A record component of a {@code record}. * @since 16 */ RECORD_COMPONENT, /** * A binding variable in a pattern. * @since 16 */ BINDING_VARIABLE;}Modifier
public enum Modifier {/** The modifier {@code public} */ PUBLIC, /** The modifier {@code protected} */ PROTECTED, /** The modifier {@code private} */ PRIVATE, /** The modifier {@code abstract} */ ABSTRACT, /** * The modifier {@code default} * @since 1.8 */ DEFAULT, /** The modifier {@code static} */ STATIC, /** * The modifier {@code sealed} * @since 17 */ SEALED, /** * The modifier {@code non-sealed} * @since 17 */ NON_SEALED { public String toString() { return "non-sealed"; } }, /** The modifier {@code final} */ FINAL, /** The modifier {@code transient} */ TRANSIENT, /** The modifier {@code volatile} */ VOLATILE, /** The modifier {@code synchronized} */ SYNCHRONIZED, /** The modifier {@code native} */ NATIVE, /** The modifier {@code strictfp} */ STRICTFP;}TypeMirror接口
public interface TypeMirror extends javax.lang.model.AnnotatedConstruct { //返回TypeKind范例,java语言中的范例.Types包罗基本范例,声明范例(类范例和接口类 //型),数组,范例变量和空范例 TypeKind getKind(); @Override List<? extends AnnotationMirror> getAnnotationMirrors(); @Override <A extends Annotation> A getAnnotation(Class<A> annotationType); @Override <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType);}public enum TypeKind { /** * The primitive type {@code boolean}. */ BOOLEAN, /** * The primitive type {@code byte}. */ BYTE, /** * The primitive type {@code short}. */ SHORT, /** * The primitive type {@code int}. */ INT, /** * The primitive type {@code long}. */ LONG, /** * The primitive type {@code char}. */ CHAR, /** * The primitive type {@code float}. */ FLOAT, /** * The primitive type {@code double}. */ DOUBLE, /** * The pseudo-type corresponding to the keyword {@code void}. * @see NoType */ VOID, /** * A pseudo-type used where no actual type is appropriate. * @see NoType */ NONE, /** * The null type. */ NULL, /** * An array type. */ ARRAY, /** * A class or interface type. */ DECLARED, /** * A class or interface type that could not be resolved. */ ERROR, /** * A type variable. */ TYPEVAR, /** * A wildcard type argument. */ WILDCARD, /** * A pseudo-type corresponding to a package element. * @see NoType */ PACKAGE, /** * A method, constructor, or initializer. */ EXECUTABLE, /** * An implementation-reserved type. * This is not the type you are looking for. */ OTHER, /** * A union type. * * @since 1.7 */ UNION, /** * An intersection type. * * @since 1.8 */ INTERSECTION, /** * A pseudo-type corresponding to a module element. * @see NoType * @since 9 */ MODULE}代码示例
获取一个类注解的值,而且获取类内里的方法
@NativeAnnotation(path = " path hahaha")public class test { public native int nativeInit(Fragment i, int j, String[] strings, ArrayList arrayList);}
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { //找出含有NativeAnnotation注解元素 Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(NativeAnnotation.class); for (Element element : elements) { //获取element元素上的注解 NativeAnnotation aah = element.getAnnotation(NativeAnnotation.class); //获取注解的值 String path = aah.path(); processingEnv.getMessager().printMessage( Diagnostic.Kind.WARNING," value path : " + path); //判定是否是类注解 if (element.getKind() == ElementKind.CLASS) { TypeElement typeElement = (TypeElement) element; //获取全类名 String className = typeElement.getQualifiedName().toString(); processingEnv.getMessager().printMessage( Diagnostic.Kind.WARNING," className: " + className); //获取类内里的元素 List<? extends Element> elements1 = typeElement.getEnclosedElements(); for (Element element1 : elements1) { //判定元素是否是方法 if (element1.getKind() == ElementKind.METHOD) { ExecutableElement executableElement = (ExecutableElement)element1; //打印方法名 processingEnv.getMessager().printMessage (Diagnostic.Kind.WARNING," method : " + executableElement.getSimpleName()); //打印方法返回值 processingEnv.getMessager().printMessage (Diagnostic.Kind.WARNING," return : " + executableElement.getReturnType().toString()); //打印方法修饰符 processingEnv.getMessager().printMessage (Diagnostic.Kind.WARNING," Modifiers : " + executableElement.getModifiers().toString()); //获取方法参数 List<? extends VariableElement> variableElements = executableElement.getParameters(); for (VariableElement element2 : variableElements) { //打印参数名称 processingEnv.getMessager().printMessage (Diagnostic.Kind.WARNING," Parame name: " + element2.getSimpleName()); //打印参数范例 processingEnv.getMessager().printMessage (Diagnostic.Kind.WARNING," Parame TypeKind : " + element2.asType().getKind().name()); //打印参数范例 processingEnv.getMessager().printMessage (Diagnostic.Kind.WARNING," Parame type : " + element2.asType().toString()); } } } } }}
value path : path hahaha����: className: com.example.annotationjnicheck.test����: method : nativeInit����: return : int����: Modifiers : [public, native]����: Parame name: i����: Parame TypeKind : DECLARED����: Parame type : android.app.Fragment����: Parame name: j����: Parame TypeKind : INT����: Parame type : int����: Parame name: strings����: Parame TypeKind : ARRAY����: Parame type : java.lang.String[]����: Parame name: arrayList����: Parame TypeKind : DECLARED����: Parame type : java.util.ArrayList参考链接:
https://blog.csdn.net/heng615975867/article/details/105072317/
http://www.360doc.com/showweb/0/0/1036633837.aspx |