Scope(作用域)
Qualifier(限定符)
註解
參考一下 兩年前收藏的一篇文章
一小時搞明白自定義註解(Annotation)
注意: 1 如果只有一個參數成員,最好把參數名稱設爲value
,當然使用的時候value=
也可以省略
2 RetentionPoicy取值,默認是classs 即 @Retention(RetentionPolicy.CLASS)
APT概念
APT(Annotation Processing Tool)即註解處理器。
APT 是一種處理註解的工具,在編譯期,通過註解生成.java文件。
使用
1 java module 引用的jar:
api 'com.google.auto.service:auto-service:1.0-rc4'
//開源java代碼生成框架
api 'com.squareup:javapoet:1.10.0'
2 processor
側重點是 javapoet常用api
1 佔位符
$L 代表的是字變量
$S for Strings(字符串)
$N for Names(我們自己生成的方法名或者變量名等等)
$T for Types (類.class,接口,枚舉)
// 註冊
@AutoService(Processor.class)
//當前註解處理器 能夠處理的註解 代替 getSupportedAnnotationTypes 方法
@SupportedAnnotationTypes({"package.annotation.TestAnnotation"})
//java 版本,代替getSupportedSourceVersion
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class TestProcessor extends AbstractProcessor {
//日誌輸出類
private Messager messager;
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {···}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (TypeElement typeElement : set) {
messager.printMessage(Diagnostic.Kind.NOTE, "charSequence---------" + roundEnvironment.getElementsAnnotatedWith(typeElement));
createJava();
}
return true;
}
// TypeSpec是類/接口/枚舉的抽象,
// MethodSpec是方法/構造函數的抽象,
// FieldSpec是成員變量/字段的抽象。
private void createJava() {
//1 創建 成員變量
FieldSpec fieldSpec = FieldSpec.builder(String.class ,"name",Modifier.PRIVATE).build();
//2.1 創建方法
// addModifiers 對方法的修飾約束,
// addParameter 添加方法參數 ,
// addStatement 方法體,
// returns 返回值
MethodSpec method = MethodSpec.methodBuilder("test")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addStatement("$T.out.println($S)", System.class, "hello")
.addStatement("$T.out.println($S)", System.class, "wrold")
.build();
//2.2 addCode
MethodSpec method2 = MethodSpec.methodBuilder("test2")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addCode(""
+ "System.out.println("+"\"hello\""+");\n"
+ "System.out.println("+"\"world\""+");\n"
)
.build();
//2.3 創建 構造方法
MethodSpec constructor = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class,"name")
.addStatement("this.$N = $N", "name", "name")
.build();
//創建 匿名類
TypeSpec comparator = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(Comparator.class, String.class))
.addMethod(MethodSpec.methodBuilder("compare")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class, "a")
.addParameter(String.class, "b")
.returns(int.class)
.addStatement("return $N.length() - $N.length()", "a", "b")
.build())
.build();
//3 創建類
TypeSpec clazz = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC,Modifier.FINAL)
.addField(fieldSpec)
.addMethod(constructor)
.addMethod(method)
.addMethod(method2)
.addMethod(MethodSpec.methodBuilder("sortByLength")
.addModifiers(Modifier.PUBLIC,Modifier.STATIC)
.addParameter(ParameterizedTypeName.get(List.class, String.class), "strings")
.addStatement("$T.sort($N, $L)", Collections.class, "strings", comparator)
.build())
.build();
//4 創建 Java文件
JavaFile javaFile = JavaFile.builder("package.hello", clazz).build();
//輸出文件
try {
javaFile.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
3 引用
使用註解 如 @TestAnnotation(“main”)
編譯成功後 使用註解生成代碼增加的功能。
參考
java註解與APT技術述
兩個例子:
Android 中的Apt基本使用
Javapoet api 重點
Android關於AutoService、Javapoet講解