在Java中,注解不僅可以提高開(kāi)發(fā)者效率,也可以讓程序變得“面向接口編程”。目前,很多框架都用到了這個(gè)技術(shù),如SpringMVC,Mybatis,Butterknife等。什么是注解請(qǐng)大家自行百度,今天我要說(shuō)的是編譯時(shí)注解的基礎(chǔ)知識(shí)(僅僅是基礎(chǔ),我也只是做個(gè)記錄)。至于為什么要說(shuō)編譯時(shí)注解呢,因?yàn)樗\(yùn)行時(shí)效率高。當(dāng)然運(yùn)行時(shí)注解也很有用,如著名的網(wǎng)絡(luò)框架Retrofit用的就是運(yùn)行時(shí)注解。
下面我們一般看代碼,一邊了解:
// com.johan.util.ioc.annotation.InjectView為要解析的注解類(lèi)名,支持通配符*,如com.johan.util.ioc.annotation.*
@SupportedAnnotationTypes("com.example.util.ioc.annotation.InjectView")
// 注明java版本
@SupportedSourceVersion(SourceVersion.RELEASE_6)
// 繼承AbstractProcessor,如果沒(méi)有找到,請(qǐng)?zhí)砑訉?duì)應(yīng)版本jar包
public class ViewInjectProcessor extends AbstractProcessor {
// Element輔佐工具
private Elements elementUtils;
@Override
public synchronized void init(ProcessingEnvironment env) {
super.init(env);
elementUtils = env.getElementUtils();
}
/**
* 解析注解
**/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
String fullClassName, className, packageName;
// InjectView.class為我的注解類(lèi)
for (Element ele : roundEnv.getElementsAnnotatedWith(InjectView.class)) {
// 打印element信息
processingEnv.getMessager().printMessage(Kind.NOTE, "ele = " + ele);
// 如果解析的是類(lèi)的注解
if (ele.getKind() == ElementKind.CLASS) {
// 類(lèi)的Element
TypeElement classElement = (TypeElement) ele;
// 包的Element,也就是類(lèi)的封裝Element
PackageElement packageElement = (PackageElement) ele.getEnclosingElement();
// 類(lèi)的全名:com.example.util.MainActivity
fullClassName= classElement.getQualifiedName().toString();
// 類(lèi)名:MainActivity
className = classElement.getSimpleName().toString();
// 包名:com.example.util
packageName = packageElement.getQualifiedName().toString();
// 獲取類(lèi)的注解值
int layoutId = classElement.getAnnotation(InjectView.class).value();
// 打印信息
processingEnv.getMessager().printMessage(Kind.NOTE, "annatated class : packageName = " + packageName + " , className = " + className + " , fqClassName = " + fqClassName);
} else if (ele.getKind() == ElementKind.FIELD) {
// 屬性的Element
VariableElement varElement = (VariableElement) ele;
// 類(lèi)的Element,就是屬性的封裝Element
TypeElement classElement = (TypeElement) ele.getEnclosingElement();
// 類(lèi)的全名:com.example.util.MainActivity
fullClassName= classElement.getQualifiedName().toString();
// 包的Element
PackageElement packageElement = elementUtils.getPackageOf(classElement);
// 包名:com.example.util
packageName = packageElement.getQualifiedName().toString();
// 類(lèi)名 :MainActivity
className = classElement.getSimpleName().toString();
// 獲取屬性的注解
int id = varElement.getAnnotation(InjectView.class).value();
String fieldName = varElement.getSimpleName().toString();
String fieldType = varElement.asType().toString();
// 打印信息
processingEnv.getMessager().printMessage(Kind.NOTE, "annatated field : fieldName = " + varElement.getSimpleName().toString() + " , id = " + id + " , fileType = " + fieldType);
}
/**
* 下面可以用JavaFileObject jfo = processingEnv.getFiler().createSourceFile方法生成JavaFileObject對(duì)象,然后Writer writer = jfo.openWriter()方法得到一個(gè)writer對(duì)象,最后java代碼文字,動(dòng)態(tài)生成的java文件
**/
return true;
}
}
}
大概就這樣了。如果有不對(duì)的地方,希望指出,謝謝!