JDK6.0的新特性之六:插入式注解處理API(PluggableAnnotationProcessingAPI)

作者: 飛翼 發(fā)表日期: 2007-01-03 20:10

插入式注解處理API(JSR 269)提供一套標準API來處理Annotations(JSR 175),實際上JSR 269不僅僅用來處理Annotation,我覺得更強大的功能是它建立了Java 語言本身的一個模型,它把method, package, constructor, type, variable, enum, annotation等Java語言元素映射為Types和Elements(兩者有什么區(qū)別?), 從而將Java語言的語義映射成為對象, 我們可以在javax.lang.model包下面可以看到這些類. 所以我們可以利用JSR 269提供的API來構建一個功能豐富的元編程(metaprogramming)環(huán)境. JSR 269用Annotation Processor在編譯期間而不是運行期間處理Annotation, Annotation Processor相當于編譯器的一個插件,所以稱為插入式注解處理.如果Annotation Processor處理Annotation時(執(zhí)行process方法)產生了新的Java代碼,編譯器會再調用一次Annotation Processor,如果第二次處理還有新代碼產生,就會接著調用Annotation Processor,直到沒有新代碼產生為止.每執(zhí)行一次process()方法被稱為一個"round",這樣整個Annotation processing過程可以看作是一個round的序列. JSR 269主要被設計成為針對Tools或者容器的API. 舉個例子,我們想建立一套基于Annotation的單元測試框架(如TestNG),在測試類里面用Annotation來標識測試期間需要執(zhí)行的測試方法,如下所示:

成都創(chuàng)新互聯(lián)成立十多年來,這條路我們正越走越好,積累了技術與客戶資源,形成了良好的口碑。為客戶提供成都網(wǎng)站設計、成都網(wǎng)站制作、網(wǎng)站策劃、網(wǎng)頁設計、域名注冊、網(wǎng)絡營銷、VI設計、網(wǎng)站改版、漏洞修補等服務。網(wǎng)站是否美觀、功能強大、用戶體驗好、性價比高、打開快等等,這些對于網(wǎng)站建設都非常重要,成都創(chuàng)新互聯(lián)通過對建站技術性的掌握、對創(chuàng)意設計的研究為客戶提供一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶,共同發(fā)展進步。

@TestMethod
public void testCheckName(){
//do something here
}

這時我們就可以用JSR 269提供的API來處理測試類,根據(jù)Annotation提取出需要執(zhí)行的測試方法.

另一個例子是如果我們出于某種原因需要自行開發(fā)一個符合Java EE 5.0的Application Server(當然不建議這樣做),我們就必須處理Common Annotations(JSR 250),Web Services Metadata(JSR 181)等規(guī)范的Annotations,這時可以用JSR 269提供的API來處理這些Annotations. 在現(xiàn)在的開發(fā)工具里面,Eclipse 3.3承諾將支持JSR 269

下面我用代碼演示如何來用JSR 269提供的API來處理Annotations和讀取Java源文件的元數(shù)據(jù)(metadata)

/**
* Created by IntelliJ IDEA.
* User: Chinajash
* Date: Dec 31, 2006
*/

@SupportedAnnotationTypes("PluggableAPT.ToBeTested")//可以用"*"表示支持所有Annotations@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class MyAnnotationProcessor extends AbstractProcessor {
private void note(String msg) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
}
public boolean process(Set annotations, RoundEnvironment roundEnv) {
//annotations的值是通過@SupportedAnnotationTypes聲明的且目標源代碼擁有的所有Annotations
for(TypeElement te:annotations){
note("annotation:"+te.toString());
}
Set elements = roundEnv.getRootElements();//獲取源代碼的映射對象 for(Element e:elements){
//獲取源代碼對象的成員 List enclosedElems = e.getEnclosedElements();
//留下方法成員,過濾掉其他成員
List ees = ElementFilter.methodsIn(enclosedElems);
for(ExecutableElement ee:ees){
note("--ExecutableElement name is "+ee.getSimpleName());
List as = ee.getAnnotationMirrors();//獲取方法的Annotations
note("--as="+as);
for(AnnotationMirror am:as){
//獲取Annotation的值
Map map= am.getElementValues();
Set ks = map.keySet();
for(ExecutableElement k:ks){//打印Annotation的每個值 AnnotationValue av = map.get(k);
note("----"+ee.getSimpleName()+"."+k.getSimpleName()+"="+av.getValue());
}
}
}
}
return false;
}
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface ToBeTested{
String owner() default "Chinajash";
String group();
}

編譯以上代碼,然后再創(chuàng)建下面的Testing對象,不要編譯Testing對象,我在后面會編譯它

public class Testing{
@ToBeTested(group="A")
public void m1(){
}
@ToBeTested(group="B",owner="QQ")
public void m2(){
}
@PostConstruct//Common Annotation里面的一個Annotation
public void m3(){
}
}

下面我用以下命令編譯Testing對象

javac -XprintRounds -processor PluggableAPT.MyAnnotationProcessor Testing.java

-XprintRounds表示打印round的次數(shù),運行上面命令后在控制臺會看到如下輸出:

Round 1:
input files: {PluggableAPT.Testing}
annotations: [PluggableAPT.ToBeTested, javax.annotation.PostConstruct]
last round: false
Note: annotation:PluggableAPT.ToBeTested
Note: --ExecutableElement name is m1
Note:
--as=@PluggableAPT.ToBeTested(group="A")
Note: ----m1.group=A
Note: --ExecutableElement name is m2
Note:
--as=@PluggableAPT.ToBeTested(group="B", owner="QQ")
Note: ----m2.group=B
Note: ----m2.owner=QQ
Note: --ExecutableElement name is m3
Note:
--as=@javax.annotation.PostConstruct
Round 2:
input files: {}
annotations: []
last round: true

本來想用JDK6.0的Compiler API來執(zhí)行上面編譯命令,可是好像現(xiàn)在Compiler API還不支持-processor參數(shù),運行時總報以下錯誤

Exception in thread "main" java.lang.IllegalArgumentException: invalid flag: -processor PluggableAPT.MyAnnotationProcessor

調用Compiler API的代碼是這樣的

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable sourcefiles = fileManager.getJavaFileObjects("Testing.java");
Set options = new HashSet();
options.add("-processor PluggableAPT.MyAnnotationProcessor");
compiler.getTask(null, fileManager, null, options, null, sourcefiles).call();

不知道這是不是Compiler API的一個bug.

[@more@]

文章標題:JDK6.0的新特性之六:插入式注解處理API(PluggableAnnotationProcessingAPI)
路徑分享:http://www.muchs.cn/article6/pgdgig.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供微信公眾號、微信小程序服務器托管、企業(yè)建站、建站公司云服務器

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化