在Java中,注解不僅可以提高開發(fā)者效率宣渗,也可以讓程序變得“面向接口編程”抖所。目前,很多框架都用到了這個技術痕囱,如SpringMVC田轧,Mybatis,Butterknife等鞍恢。什么是注解請大家自行百度傻粘,今天我要說的是編譯時注解的基礎知識(僅僅是基礎每窖,我也只是做個記錄)。至于為什么要說編譯時注解呢弦悉,因為他運行時效率高窒典。當然運行時注解也很有用,如著名的網絡框架Retrofit用的就是運行時注解警绩。
下面我們一般看代碼崇败,一邊了解:
// com.johan.util.ioc.annotation.InjectView為要解析的注解類名,支持通配符*肩祥,如com.johan.util.ioc.annotation.*
@SupportedAnnotationTypes("com.example.util.ioc.annotation.InjectView")
// 注明java版本
@SupportedSourceVersion(SourceVersion.RELEASE_6)
// 繼承AbstractProcessor,如果沒有找到缩膝,請?zhí)砑訉姹緅ar包
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為我的注解類
for (Element ele : roundEnv.getElementsAnnotatedWith(InjectView.class)) {
// 打印element信息
processingEnv.getMessager().printMessage(Kind.NOTE, "ele = " + ele);
// 如果解析的是類的注解
if (ele.getKind() == ElementKind.CLASS) {
// 類的Element
TypeElement classElement = (TypeElement) ele;
// 包的Element混狠,也就是類的封裝Element
PackageElement packageElement = (PackageElement) ele.getEnclosingElement();
// 類的全名:com.example.util.MainActivity
fullClassName= classElement.getQualifiedName().toString();
// 類名:MainActivity
className = classElement.getSimpleName().toString();
// 包名:com.example.util
packageName = packageElement.getQualifiedName().toString();
// 獲取類的注解值
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;
// 類的Element,就是屬性的封裝Element
TypeElement classElement = (TypeElement) ele.getEnclosingElement();
// 類的全名:com.example.util.MainActivity
fullClassName= classElement.getQualifiedName().toString();
// 包的Element
PackageElement packageElement = elementUtils.getPackageOf(classElement);
// 包名:com.example.util
packageName = packageElement.getQualifiedName().toString();
// 類名 :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對象疾层,然后Writer writer = jfo.openWriter()方法得到一個writer對象将饺,最后java代碼文字,動態(tài)生成的java文件
**/
return true;
}
}
}
大概就這樣了痛黎。如果有不對的地方予弧,希望指出,謝謝湖饱!