[轉]java註解與APT技術
阿新 • • 發佈:2018-05-31
pretty runt src ons data exception clas -m animal
下面是一個簡單的自定義註解的栗子:
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()方法中,加入更多的業務邏輯,以實現特定功能。
[轉]java註解與APT技術