一:註解基礎學習
註解從含義上講是一種元數據,本質上只是對代碼的一種註釋說明,因爲有了註解的解析纔有了相應的功能。如果沒有註解解析產生功能,它還不如註釋清晰。從結構上看,註解編譯後就是一個接口
元註解
元註解:元註解是一種基本註解,在定義註解時使用,主要定義註解的作用域,生命週期等等
- @Retention:定義註解的生命週期
- RetentionPolicy.SOURCE 註解只在源碼階段保留,在編譯器進行編譯時它將被丟棄忽視。
- RetentionPolicy.CLASS 註解只被保留到編譯進行的時候,它並不會被加載到 JVM 中。
- RetentionPolicy.RUNTIME 註解可以保留到程序運行的時候,它會被加載進入到 JVM 中,所以在程序運行時可以獲取到它們
- @Documented
將註解中的元素包含到 Javadoc 中去。 - @Target
限定了運用的場景。方法,字段,類。ElementType列舉了枚舉值表示作用域 - @Inherited
如果一個註解使用@Inherited標記,那麼使用當前註解的類的子類自動添加當前註解(子類沒有顯式使用註解) - @Repeatable
java8開始引入,定義的註解可以在同一個地方重複使用
註解的定義和屬性
註解定義關鍵字是@interface,註解只有成員變量,沒有方法。方法名定義了該成員變量的名字,其返回值定義了該成員變量的類型
定義了 TestAnnotation 這個註解中擁有 id 和 msg 兩個屬性。在使用的時候,我們應該給它們進行賦值。賦值的方式是在註解的括號內以 value=”” 形式,多個屬性之前用 ,隔開。
注意點:
- 定義屬性時它的類型必須是 8 種基本數據類型外加 類、接口、註解及它們的數組
- 可以給屬性設置默認值
public int id() default -1;
- 一個註解內僅僅只有一個名字爲 value 的屬性時,應用這個註解時可以直接接屬性值填寫到括號內。如果有多個屬性,使用時省略屬性名默認指的就是value屬性
二:編譯時解析註解
在使用javac編譯java代碼時,通過APT(註解處理器)技術獲取.java文件中的註解信息,生成新的java代碼(可以使用javapoet生成代碼),可以實現一些功能。例如:lombok工具包
使用APT;
步驟1:繼承AbstractProcessor,重寫process方法
使用@AutoService生成META-INF\services\javax.annotation.processing.Processor
@AutoService的pom
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.0-rc6</version>
</dependency>
使用:
process生成helloworld
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
System.out.println("------ process -----");
//MethodSpec這個類是要引入'com.squareup:javapoet:1.8.0'包,方便通過代碼創建java文件
MethodSpec main = MethodSpec.methodBuilder("main")
//.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
//netstat -an | grep .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
JavaFile javaFile = JavaFile.builder("com.txd.annotaionlearn", helloWorld)
.build();
try {
//這裏的輸出要在Gradle Console中看
javaFile.writeTo(System.out);
javaFile.writeTo(new File("E:\\10.workspace\\2.ST(4.0)\\test\\src\\main\\java\\com\\txd\\annotaionlearn\\model"));
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
編譯,安裝到本地倉庫,clean install
步驟2:在maven工程中使用以上的自定義註解處理器,涉及2個插件
maven-processor-plugin和maven-compiler-plugin
此處我通過maven-compiler-plugin來使用自定義annotationprocessor
然後,mvn clean compile
會發現在控制檯上:
本地生成helloworld文件
此次生成代碼用到了java類庫javapoet
三:運行時解析註解
註解類型必須是:@Retention(RetentionPolicy.RUNTIME)
運用反射技術提取註解:使用Class 對象的幾個方法
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass){} ;
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {};
public Annotation[] getAnnotations() {};
然後就可以獲取註解上的參數,做邏輯處理
四:spi使用@AutoService
spi在很多地方已經有使用:jdbc4.0以後,dubbo
五:常見的操作源代碼字節碼的庫
字節碼:javasist,cglib,ASM
源碼:Javapoet
五:參考博客
- https://www.cnblogs.com/guyuehuanhuan/p/9185899.html
- https://juejin.im/entry/585617d6128fe1006994f992
- https://www.jianshu.com/p/c04619b37440
- https://blog.csdn.net/jjxojm/article/details/90349756
- https://www.jianshu.com/p/086fe09188ea