[轉]java注解與APT技術


 

下面是一個簡單的自定義注解的栗子:

package annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 動物名稱注解 * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AnimalName { String value() default ""; }

 

定義了注解,並在需要的時候給相關類,類屬性加上注解信息,如果沒有響應的注解信息處理流程,注解可以說是沒有實用價值,接下來要介紹的是java的APT(Annotation Process Tool)技術,用於處理自定義注解。

2,APT技術

APT(Annotation Process Tool),是一種在代碼編譯時處理注解,按照一定的規則,生成相應的java文件,多用於對自定義注解的處理,目前比較流行的Dagger2, ButterKnife, EventBus3都是采用APT技術,對運行時的性能影響很小。我們通過自定義注解的方式,來了解一下如何使用APT:

1,自定義注解:

@Target({ElementType.TYPE}) ---作用范圍 Class @Retention(RetentionPolicy.CLASS) ---生命周期:僅保留到.class文件 public @interface Route { /** Path of route*/ String value(); ---類似於成員變量 }

 

2,使用方式

@Route(path = "/test/activity2") public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test2); } }

JVM默認只會處理@override等語言自帶的注解,對於自定義的注解,需要我們自己處理,java提供了一個名為AbstractProcessor.java的抽象類,我們只要繼承該類,就實現自己的注解處理器,來處理自定義的@Route注解

public class RouteProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment env){ // 主要做一些初始化操作 } @Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { //具體處理注解的邏輯,控制代碼的生成 processAnnotations(); } @Override public Set<String> getSupportedAnnotationTypes() { // 支持處理的注解類型, 在這里就是@Route } @Override public SourceVersion getSupportedSourceVersion() { //java版本 如:jdk1.6or jdk1.7 } }

3,自定義Processor

@AutoService(Processor.class) public class HelloProcessor extends AbstractProcessor { /** 文件相關的輔助類 用於生成新的源文件、class等 */ private Filer mFiler; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); mFiler = processingEnv.getFiler(); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { // 構建方法 此處使用到了square公司的javapoet庫,用來輔助生成 類的代碼 MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("show") .addModifiers(Modifier.PUBLIC); methodBuilder.addStatement("String test = \"$N\" ","hello annotation world!"); /** 構建類 */ TypeSpec finderClass = TypeSpec.classBuilder("Hello$$Inject") .addModifiers(Modifier.PUBLIC) .addMethod(methodBuilder.build()) .build(); try { JavaFile.builder("com.win.test",finderClass).build().writeTo(mFiler); } catch (IOException e) { e.printStackTrace(); } return true; } // 支持的注解類型 @Override public Set<String> getSupportedAnnotationTypes() { Set<String> types = new LinkedHashSet<>(); types.add(Hello.class.getCanonicalName()); return types; } @Override public SourceVersion getSupportedSourceVersion() { return super.getSupportedSourceVersion(); } }

在AS工程中使用

@Hello("MainTest") //自定義的Hello注解 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }

在項目App module的build目錄下,便會生成對應的java類文件:

這里寫圖片描述

這個只是簡單的栗子,我們可以在process()方法中,加入更多的業務邏輯,以實現特定功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM