• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Shuffy

            不斷的學(xué)習(xí),不斷的思考,才能不斷的進(jìn)步.Let's do better together!
            posts - 102, comments - 43, trackbacks - 0, articles - 19

            Java Annotation 高級(jí)應(yīng)用

            Posted on 2008-12-09 15:44 Shuffy 閱讀(815) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Java
            原文:http://www.matrix.org.cn/resource/article/44/44062_Java+Annotation+Apt.html
            前言:
            前不久在matrix上先后發(fā)表了
            《java annotation 入門》、《java annotation 手冊(cè)》兩篇文章,比較全面的對(duì)java annotation的語法、原理、使用三方面進(jìn)行了闡述。由于《入門》中的簡(jiǎn)單例程雖然簡(jiǎn)單明了的說明了annotation用法,但給大家的感覺可能是意猶未見,所以在此行文《java annotation高級(jí)應(yīng)用》,具體實(shí)例化解釋annotation和annotation processing tool(APT)的使用。望能對(duì)各位的有所幫助。

            一、摘要:
            《java annotation高級(jí)應(yīng)用》具體實(shí)例化解釋annotation和annotation processing tool(APT)的使用。望能對(duì)各位的有所幫助。本文列舉了用于演示annotation的BRFW演示框架、演示APT的apt代碼實(shí)例,并對(duì)其進(jìn)行較為深度的分析,希望大家多多提意見。

            二、annotation實(shí)例分析
            1.BRFW(Beaninfo Runtime FrameWork)定義:
            本人編寫的一個(gè)annotation功能演示框架。顧名思義,BRFW就是在運(yùn)行時(shí)取得bean信息的框架。

            2.BRFW的功能:
            A.源代碼級(jí)annotation:在bean的源代碼中使用annotation定義bean的信息;
            B.運(yùn)行時(shí)獲取bean數(shù)據(jù):在運(yùn)行時(shí)分析bean class中的annotation,并將當(dāng)前bean class中field信息取出,功能類似xdoclet;
            C.運(yùn)行時(shí)bean數(shù)據(jù)的xml綁定:將獲得的bean數(shù)據(jù)構(gòu)造為xml文件格式展現(xiàn)。熟悉j2ee的朋友知道,這個(gè)功能類似jaxb。

            3.BRFW框架:
            BRFW主要包含以下幾個(gè)類:
            A.Persistent類:定義了用于修飾類的固有類型成員變量的annotation。
            B.Exportable類:定義了用于修飾Class的類型的annotation。
            C.ExportToXml類:核心類,用于完成BRFW的主要功能:將具有Exportable Annotation的bean對(duì)象轉(zhuǎn)換為xml格式文本。
            D.AddressForTest類:被A和B修飾過的用于測(cè)試目的的地址bean類。其中包含了地址定義所必需的信息:國(guó)家、省級(jí)、城市、街道、門牌等。
            E.AddressListForTest類:被A和B修飾過的友人通訊錄bean類。其中包含了通訊錄所必備的信息:友人姓名、年齡、電話、住址(成員為AddressForTest類型的 ArrayList)、備注。需要說明的是電話這個(gè)bean成員變量是由字符串類型組成的ArrayList類型。由于朋友的住址可能不唯一,故這里的住址為由AddressForTest類型組成的ArrayList。
            從上面的列表中,可以發(fā)現(xiàn)A、B用于修飾bean類和其類成員;C主要用于取出bean類的數(shù)據(jù)并將其作xml綁定,代碼中使用了E作為測(cè)試類;E中可能包含著多個(gè)D。
            在了解了這個(gè)簡(jiǎn)單框架后,我們來看一下BRFW的代碼吧!

            4.BRFW源代碼分析:
            A.Persistent類:
            清單1:

            package com.bjinfotech.practice.annotation.runtimeframework;

            import java.lang.annotation.*;

            /**
            * 用于修飾類的固有類型成員變量的annotation
            * @author cleverpig
            *
            */
            @Retention(RetentionPolicy.RUNTIME)
            @Target(ElementType.FIELD)
            public @interface Persistent {
                    String value() default "";
            }


            B.Exportable類:
            清單2:

            package com.bjinfotech.practice.annotation.runtimeframework;

            import java.lang.annotation.*;

            /**
            * 用于修飾類的類型的annotation
            * @author cleverpig
            *
            */
            @Retention(RetentionPolicy.RUNTIME)
            @Target(ElementType.TYPE)
            public @interface Exportable {
                    //名稱
                    String name() default "";
                    //描述
                    String description() default "";
                    //省略name和description后,用來保存name值
                    String value() default "";
                    
            }


            C.AddressForTest類:
            清單3:

            package com.bjinfotech.practice.annotation.runtimeframework;

            /**
            * 用于測(cè)試的地址類
            * @author cleverpig
            *
            */
            @Exportable("address")
            public class AddressForTest {
                    //國(guó)家
                    @Persistent
                    private String country=null;
                    
                    //省級(jí)
                    @Persistent
                    private String province=null;
                    
                    //城市
                    @Persistent
                    private String city=null;
                    
                    //街道
                    @Persistent
                    private String street=null;

                    //門牌
                    @Persistent
                    private String doorplate=null;
                    
                    public AddressForTest(String country,String province,
                                    String city,String street,String doorplate){
                            this.country=country;
                            this.province=province;
                            this.city=city;
                            this.street=street;
                            this.doorplate=doorplate;
                    }
                    
            }


            D.AddressListForTest類:
            清單4:

            package com.bjinfotech.practice.annotation.runtimeframework;

            import java.util.*;

            /**
            * 友人通訊錄
            * 包含:姓名、年齡、電話、住址(多個(gè))、備注
            * @author cleverpig
            *
            */
            @Exportable(name="addresslist",description="address list")
            public class AddressListForTest {
                    //友人姓名
                    @Persistent
                    private String friendName=null;
                    
                    //友人年齡
                    @Persistent
                    private int age=0;
                    
                    //友人電話
                    @Persistent
                    private ArrayList<String> telephone=null;
                    
                    //友人住址:家庭、單位
                    @Persistent
                    private ArrayList<AddressForTest> AddressForText=null;
                    
                    //備注
                    @Persistent
                    private String note=null;
                    
                    public AddressListForTest(String name,int age,
                                    ArrayList<String> telephoneList,
                                    ArrayList<AddressForTest> addressList,
                                    String note){
                            this.friendName=name;
                            this.age=age;
                            this.telephone=new ArrayList<String>(telephoneList);
                            this.AddressForText=new ArrayList<AddressForTest>(addressList);
                            this.note=note;
                            
                    }
            }


            E.ExportToXml類:
            清單5:

            package com.bjinfotech.practice.annotation.runtimeframework;

            import java.lang.reflect.Field;
            import java.util.Collection;
            import java.util.Iterator;
            import java.util.Map;
            import java.util.ArrayList;

            /**
            * 將具有Exportable Annotation的對(duì)象轉(zhuǎn)換為xml格式文本
            * @author cleverpig
            *
            */
            public class ExportToXml {
                    /**
                     * 返回對(duì)象的成員變量的值(字符串類型)
                     * @param field 對(duì)象的成員變量
                     * @param fieldTypeClass 對(duì)象的類型
                     * @param obj 對(duì)象
                     * @return 對(duì)象的成員變量的值(字符串類型)
                     */
                    private String getFieldValue(Field field,Class fieldTypeClass,Object obj){
                            String value=null;
                            
                            try{
                                    if (fieldTypeClass==String.class){
                                            value=(String)field.get(obj);
                                    }
                                    else if (fieldTypeClass==int.class){
                                            value=Integer.toString(field.getInt(obj));
                                    }
                                    else if (fieldTypeClass==long.class){
                                            value=Long.toString(field.getLong(obj));
                                    }
                                    else if (fieldTypeClass==short.class){
                                            value=Short.toString(field.getShort(obj));
                                    }
                                    else if (fieldTypeClass==float.class){
                                            value=Float.toString(field.getFloat(obj));
                                    }
                                    else if (fieldTypeClass==double.class){
                                            value=Double.toString(field.getDouble(obj));
                                    }
                                    else if (fieldTypeClass==byte.class){
                                            value=Byte.toString(field.getByte(obj));
                                    }
                                    else if (fieldTypeClass==char.class){
                                            value=Character.toString(field.getChar(obj));
                                    }
                                    else if (fieldTypeClass==boolean.class){
                                            value=Boolean.toString(field.getBoolean(obj));
                                    }
                            }
                            catch(Exception ex){
                                    ex.printStackTrace();
                                    value=null;
                            }
                            return value;
                    }
                    
                    /**
                     * 輸出對(duì)象的字段,當(dāng)對(duì)象的字段為Collection或者M(jìn)ap類型時(shí),要調(diào)用exportObject方法繼續(xù)處理
                     * @param obj 被處理的對(duì)象
                     * @throws Exception
                     */
                    public void exportFields(Object obj) throws Exception{
                            Exportable exportable=obj.getClass().getAnnotation(Exportable.class);        
                            if (exportable!=null){
                                    if (exportable.value().length()>0){
            //                                System.out.println("Class annotation Name:"+exportable.value());
                                    }
                                    else{
            //                                System.out.println("Class annotation Name:"+exportable.name());
                                    }
                            }
                            else{
            //                        System.out.println(obj.getClass()+"類不是使用Exportable標(biāo)注過的");
                            }
                            
                            //取出對(duì)象的成員變量
                            Field[] fields=obj.getClass().getDeclaredFields();
                            
                            for(Field field:fields){
                                    //獲得成員變量的標(biāo)注
                                    Persistent fieldAnnotation=field.getAnnotation(Persistent.class);
                                    if (fieldAnnotation==null){
                                            continue;
                                    }
                                    //重要:避免java虛擬機(jī)檢查對(duì)私有成員的訪問權(quán)限
                                    field.setAccessible(true);
                                    Class typeClass=field.getType();
                                    String name=field.getName();
                                    String value=getFieldValue(field,typeClass,obj);
                                    
                                    //如果獲得成員變量的值,則輸出
                                    if (value!=null){
                                            System.out.println(getIndent()+"<"+name+">\n"
                                                            +getIndent()+"\t"+value+"\n"+getIndent()+"</"+name+">");
                                    }
                                    //處理成員變量中類型為Collection或Map
                                    else if ((field.get(obj) instanceof Collection)||
                                                    (field.get(obj) instanceof Map)){
                                            exportObject(field.get(obj));
                                    }
                                    else{
                                            exportObject(field.get(obj));
                                    }
                                    
                            }
                    }
                    
                    //縮進(jìn)深度
                    int levelDepth=0;
                    //防止循環(huán)引用的檢查者,循環(huán)引用現(xiàn)象如:a包含b,而b又包含a
                    Collection<Object> cyclicChecker=new ArrayList<Object>();
                    
                    /**
                     * 返回縮進(jìn)字符串
                     * @return
                     */
                    private String getIndent(){
                            String s="";
                            for(int i=0;i<levelDepth;i++){
                                    s+="\t";
                            }
                            return s;
                    }
                    /**
                     * 輸出對(duì)象,如果對(duì)象類型為Collection和Map類型,則需要遞歸調(diào)用exportObject進(jìn)行處理
                     * @param obj
                     * @throws Exception
                     */
                    public void exportObject(Object obj) throws Exception{
                            Exportable exportable=null;
                            String elementName=null;
                            
                            //循環(huán)引用現(xiàn)象處理
                            if (cyclicChecker.contains(obj)){
                                    return;
                            }
                            
                            cyclicChecker.add(obj);
                            
                            //首先處理Collection和Map類型
                            if (obj instanceof Collection){
                                    for(Iterator i=((Collection)obj).iterator();i.hasNext();){
                                            exportObject(i.next());
                                    }
                            }
                            else if (obj instanceof Map){
                                    for(Iterator i=((Map)obj).keySet().iterator();i.hasNext();){
                                            exportObject(i.next());
                                    }
                            }
                            else{

                                    exportable=obj.getClass().getAnnotation(Exportable.class);
                                    //如果obj已經(jīng)被Exportable Annotation修飾過了(注意annotation是具有繼承性的),
                                    //則使用其name作為輸出xml的元素name
                                    if (exportable!=null){
                                            if (exportable.value().length()>0){
                                                    elementName=exportable.value();
                                            }
                                            else{
                                                    elementName=exportable.name();
                                            }
                                    }
                                    //未被修飾或者Exportable Annotation的值為空字符串,
                                    //則使用類名作為輸出xml的元素name
                                    if (exportable==null||elementName.length()==0){
                                            elementName=obj.getClass().getSimpleName();
                                    }
                                    //輸出xml元素頭
                                    System.out.println(getIndent()+"<"+elementName+">");
                                    levelDepth++;
                                    //如果沒有被修飾,則直接輸出其toString()作為元素值
                                    if (exportable==null){
                                            System.out.println(getIndent()+obj.toString());
                                    }
                                    //否則將對(duì)象的成員變量導(dǎo)出為xml
                                    else{
                                            exportFields(obj);
                                    }
                                    levelDepth--;
                                    //輸出xml元素結(jié)尾
                                    System.out.println(getIndent()+"</"+elementName+">");
                                    
                            }
                            cyclicChecker.remove(obj);
                    }
                    
                    public static void main(String[] argv){
                            try{
                                    AddressForTest ad=new AddressForTest("China","Beijing",
                                                    "Beijing","winnerStreet","10");
                                    
                                    ExportToXml test=new ExportToXml();
                                    
                                    ArrayList<String> telephoneList=new ArrayList<String>();
                                    telephoneList.add("66608888");
                                    telephoneList.add("66608889");
                                    
                                    ArrayList<AddressForTest> adList=new ArrayList<AddressForTest>();
                                    adList.add(ad);
                                    
                                    AddressListForTest adl=new AddressListForTest("coolBoy",
                                                    18,telephoneList,adList,"some words");
                                    
                                    test.exportObject(adl);
                            }
                            catch(Exception ex){
                                    ex.printStackTrace();
                            }
                    }
            }


            在ExportToXml 類之前的類比較簡(jiǎn)單,這里必須說明一下ExportToXml類:此類的核心函數(shù)是exportObject和exportFields方法,前者輸出對(duì)象的xml信息,后者輸出對(duì)象成員變量的信息。由于對(duì)象類型和成員類型的多樣性,所以采取了以下的邏輯:

            在exportObject方法中,當(dāng)對(duì)象類型為Collection和Map類型時(shí),則需要遞歸調(diào)用exportObject進(jìn)行處理;
            而如果對(duì)象類型不是Collection和Map類型的話,將判斷對(duì)象類是否被Exportable annotation修飾過:
            如果沒有被修飾,則直接輸出<對(duì)象類名>對(duì)象.toString()</對(duì)象類名>作為xml綁定結(jié)果的一部分;
            如果被修飾過,則需要調(diào)用exportFields方法對(duì)對(duì)象的成員變量進(jìn)行xml綁定。

            在exportFields 方法中,首先取出對(duì)象的所有成員,然后獲得被Persisitent annotation修飾的成員。在其后的一句:field.setAccessible(true)是很重要的,因?yàn)閎ean類定義中的成員訪問修飾都是private,所以為了避免java虛擬機(jī)檢查對(duì)私有成員的訪問權(quán)限,加上這一句是必需的。接著后面的語句便是輸出<成員名>成員值 </成員名>這樣的xml結(jié)構(gòu)。像在exportObject方法中一般,仍然需要判斷成員類型是否為Collection和Map類型,如果為上述兩種類型之一,則要在exportFields中再次調(diào)用exportObject來處理這個(gè)成員。

            在main方法中,本人編寫了一段演示代碼:建立了一個(gè)由單個(gè)友人地址類(AddressForTest)組成的ArrayList作為通訊錄類(AddressForTest)的成員的通訊錄對(duì)象,并且輸出這個(gè)對(duì)象的xml綁定,運(yùn)行結(jié)果如下:

            清單6:

            <addresslist>
                    <friendName>
                            coolBoy
                    </friendName>
                    <age>
                            18
                    </age>
                    <String>
                            66608888
                    </String>
                    <String>
                            66608889
                    </String>
                    <address>
                            <country>
                                    China
                            </country>
                            <province>
                                    Beijing
                            </province>
                            <city>
                                    Beijing
                            </city>
                            <street>
                                    winnerStreet
                            </street>
                            <doorplate>
                                    10
                            </doorplate>
                    </address>
                    <note>
                            some words
                    </note>
            </addresslist>


            三、APT實(shí)例分析:
            1.何謂APT?
            根據(jù)sun官方的解釋,APT(annotation processing tool)是一個(gè)命令行工具,它對(duì)源代碼文件進(jìn)行檢測(cè)找出其中的annotation后,使用annotation processors來處理annotation。而annotation processors使用了一套反射API并具備對(duì)JSR175規(guī)范的支持。
            annotation processors處理annotation的基本過程如下:首先,APT運(yùn)行annotation processors根據(jù)提供的源文件中的annotation生成源代碼文件和其它的文件(文件具體內(nèi)容由annotation processors的編寫者決定),接著APT將生成的源代碼文件和提供的源文件進(jìn)行編譯生成類文件。
            簡(jiǎn)單的和前面所講的annotation 實(shí)例BRFW相比,APT就像一個(gè)在編譯時(shí)處理annotation的javac。而且從sun開發(fā)者的blog中看到,java1.6 beta版中已將APT的功能寫入到了javac中,這樣只要執(zhí)行帶有特定參數(shù)的javac就能達(dá)到APT的功能。

            2.為何使用APT?
            使用APT主要目的是簡(jiǎn)化開發(fā)者的工作量,因?yàn)锳PT可以在編譯程序源代碼的同時(shí),生成一些附屬文件(比如源文件、類文件、程序發(fā)布描述文字等),這些附屬文件的內(nèi)容也都是與源代碼相關(guān)的。換句話說,使用APT就是代替了傳統(tǒng)的對(duì)代碼信息和附屬文件的維護(hù)工作。使用過hibernate或者beehive等軟件的朋友可能深有體會(huì)。APT可以在編譯生成代碼類的同時(shí)將相關(guān)的文件寫好,比如在使用beehive時(shí),在代碼中使用annotation聲明了許多 struct要用到的配置信息,而在編譯后,這些信息會(huì)被APT以struct配置文件的方式存放。

            3.如何定義processor?
            A.APT工作過程:
            從整個(gè)過程來講,首先APT檢測(cè)在源代碼文件中哪些annotation存在。然后APT將查找我們編寫的annotation processor factories類,并且要求factories類提供處理源文件中所涉及的annotation的annotation processor。接下來,一個(gè)合適的annotation processors將被執(zhí)行,如果在processors生成源代碼文件時(shí),該文件中含有annotation,則APT將重復(fù)上面的過程直到?jīng)]有新文件生成。

            B.編寫annotation processors:
            編寫一個(gè)annotation processors需要使用java1.5 lib目錄中的tools.jar提供的以下4個(gè)包:
            com.sun.mirror.apt: 和APT交互的接口;
            com.sun.mirror.declaration: 用于模式化類成員、類方法、類聲明的接口;
            com.sun.mirror.type: 用于模式化源代碼中類型的接口;
            com.sun.mirror.util: 提供了用于處理類型和聲明的一些工具。

            每個(gè)processor實(shí)現(xiàn)了在com.sun.mirror.apt包中的AnnotationProcessor接口,這個(gè)接口有一個(gè)名為 “process”的方法,該方法是在APT調(diào)用processor時(shí)將被用到的。一個(gè)processor可以處理一種或者多種annotation類型。
            一個(gè)processor實(shí)例被其相應(yīng)的工廠返回,此工廠為AnnotationProcessorFactory接口的實(shí)現(xiàn)。APT將調(diào)用工廠類的getProcessorFor方法來獲得processor。在調(diào)用過程中,APT將提供給工廠類一個(gè) AnnotationProcessorEnvironment 類型的processor環(huán)境類對(duì)象,在這個(gè)環(huán)境對(duì)象中,processor將找到其執(zhí)行所需要的每件東西,包括對(duì)所操作的程序結(jié)構(gòu)的參考,與APT通訊并合作一同完成新文件的建立和警告/錯(cuò)誤信息的傳輸。

            提供工廠類有兩個(gè)方式:通過APT的“-factory”命令行參數(shù)提供,或者讓工廠類在APT的發(fā)現(xiàn)過程中被自動(dòng)定位(關(guān)于發(fā)現(xiàn)過程詳細(xì)介紹請(qǐng)看http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html)。前者對(duì)于一個(gè)已知的factory來講是一種主動(dòng)而又簡(jiǎn)單的方式;而后者則是需要在jar文件的META-INF/services目錄中提供一個(gè)特定的發(fā)現(xiàn)路徑:
            在包含factory類的jar文件中作以下的操作:在META-INF/services目錄中建立一個(gè)名為 com.sun.mirror.apt.AnnotationProcessorFactory 的UTF-8編碼文件,在文件中寫入所有要使用到的factory類全名,每個(gè)類為一個(gè)單獨(dú)行。

            4.一個(gè)簡(jiǎn)單的APT實(shí)例分析:
            A.實(shí)例構(gòu)成:
            Review類:定義Review Annotation;
            ReviewProcessorFactory類:生成ReviewProcessor的工廠類;
            ReviewProcessor類:定義處理Review annotation的Processor;
            ReviewDeclarationVisitor類:定義Review annotation聲明訪問者,ReviewProcessor將要使用之對(duì)Class進(jìn)行訪問。
            runapt.bat:定義了使用自定義的ReviewProcessor對(duì)Review類源代碼文件進(jìn)行處理的APT命令行。

            B.Review類:
            清單7:

            package com.bjinfotech.practice.annotation.apt;

            /**
            * 定義Review Annotation
            * @author cleverpig
            *
            */
            public @interface Review {
                    public static enum TypeEnum{EXCELLENT,NICE,NORMAL,BAD};
                    TypeEnum type();
                    String name() default "Review";
            }


            C.ReviewProcessorFactory類:
            清單8:

            package com.bjinfotech.practice.annotation.apt;

            import java.util.Collection;
            import java.util.Set;
            import java.util.Arrays;
            import com.sun.mirror.apt.*;
            import com.sun.mirror.declaration.AnnotationTypeDeclaration;
            import com.sun.mirror.apt.AnnotationProcessorEnvironment;
            //請(qǐng)注意為了方便,使用了靜態(tài)import
            import static java.util.Collections.unmodifiableCollection;
            import static java.util.Collections.emptySet;

            /**
            * 生成ReviewProcessor的工廠類
            * @author cleverpig
            *
            */
            public class ReviewProcessorFactory implements AnnotationProcessorFactory{
                    /**
                     * 獲得針對(duì)某個(gè)(些)類型聲明定義的Processor
                     * @param atds 類型聲明集合
                     * @param env processor環(huán)境
                     */
                    public AnnotationProcessor getProcessorFor(
                                    Set<AnnotationTypeDeclaration> atds,
                                    AnnotationProcessorEnvironment env){
                            return new ReviewProcessor(env);
                    }
                    /**
                     * 定義processor所支持的annotation類型
                     * @return processor所支持的annotation類型的集合
                     */
                    public Collection<String>         supportedAnnotationTypes(){
                            //“*”表示支持所有的annotation類型
                            //當(dāng)然也可以修改為“foo.bar.*”、“foo.bar.Baz”,來對(duì)所支持的類型進(jìn)行修飾
                        return unmodifiableCollection(Arrays.asList("*"));
                }
                    
                    /**
                     * 定義processor支持的選項(xiàng)
                     * @return processor支持選項(xiàng)的集合
                     */
                    public Collection<String>         supportedOptions(){
                            //返回空集合
                        return emptySet();
                }
                    
                    public static void main(String[] argv){
                            System.out.println("ok");
                    }
            }


            D.ReviewProcessor類:
            清單9:

            package com.bjinfotech.practice.annotation.apt;

            import com.sun.mirror.apt.AnnotationProcessor;
            import com.sun.mirror.apt.AnnotationProcessorEnvironment;
            import com.sun.mirror.declaration.TypeDeclaration;
            import com.sun.mirror.util.DeclarationVisitors;
            import com.sun.mirror.util.DeclarationVisitor;

            /**
            * 定義Review annotation的Processor
            * @author cleverpig
            *
            */
            public class ReviewProcessor implements AnnotationProcessor{
                    //Processor所工作的環(huán)境
                    AnnotationProcessorEnvironment env=null;
                    
                    /**
                     * 構(gòu)造方法
                     * @param env 傳入processor環(huán)境
                     */
                    public ReviewProcessor(AnnotationProcessorEnvironment env){
                            this.env=env;
                    }
                    
                    /**
                     * 處理方法:查詢processor環(huán)境中的類型聲明,
                     */
                    public void process(){
                            //查詢processor環(huán)境中的類型聲明
                            for(TypeDeclaration type:env.getSpecifiedTypeDeclarations()){
                                    //返回對(duì)類進(jìn)行掃描、訪問其聲明時(shí)使用的DeclarationVisitor,
                                    //傳入?yún)?shù):new ReviewDeclarationVisitor(),為掃描開始前進(jìn)行的對(duì)類聲明的處理
                                    //        DeclarationVisitors.NO_OP,表示在掃描完成時(shí)進(jìn)行的對(duì)類聲明不做任何處理
                                    DeclarationVisitor visitor=DeclarationVisitors.getDeclarationScanner(
                                                    new ReviewDeclarationVisitor(),DeclarationVisitors.NO_OP);
                                    //應(yīng)用DeclarationVisitor到類型
                                    type.accept(visitor);
                            }
                    }
            }


            E.ReviewDeclarationVisitor類:
            清單10:

            package com.bjinfotech.practice.annotation.apt;

            import com.sun.mirror.util.*;
            import com.sun.mirror.declaration.*;

            /**
            * 定義Review annotation聲明訪問者
            * @author cleverpig
            *
            */
            public class ReviewDeclarationVisitor extends SimpleDeclarationVisitor{
                    /**
                     * 定義訪問類聲明的方法:打印類聲明的全名
                     * @param cd 類聲明對(duì)象
                     */
                    public void visitClassDeclaration(ClassDeclaration cd){
                            System.out.println("獲取Class聲明:"+cd.getQualifiedName());
                    }
                    
                    public void visitAnnotationTypeDeclaration(AnnotationTypeDeclaration atd){
                            System.out.println("獲取Annotation類型聲明:"+atd.getSimpleName());
                    }
                    
                    public void visitAnnotationTypeElementDeclaration(AnnotationTypeElementDeclaration aed){
                            System.out.println("獲取Annotation類型元素聲明:"+aed.getSimpleName());
                    }
            }


            F.runapt.bat文件內(nèi)容如下:
            清單11:

            E:
            rem 項(xiàng)目根目錄
            set PROJECT_ROOT=E:\eclipse3.1RC3\workspace\tigerFeaturePractice
            rem 包目錄路徑
            set PACKAGEPATH=com\bjinfotech\practice\annotation\apt
            rem 運(yùn)行根路徑
            set RUN_ROOT=%PROJECT_ROOT%\build
            rem 源文件所在目錄路徑
            set SRC_ROOT=%PROJECT_ROOT%\test
            rem 設(shè)置Classpath
            set CLASSPATH=.;%JAVA_HOME%;%JAVA_HOME%/lib/tools.jar;%RUN_ROOT%

            cd %SRC_ROOT%\%PACKAGEPATH%
            apt -nocompile -factory com.bjinfotech.practice.annotation.apt.ReviewProcessorFactory  ./*.java


            四、參考資源:
            http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
            久久精品国产福利国产秒| 99久久久精品| 久久久久久久国产免费看| 色综合久久天天综合| 国产成人AV综合久久| 久久午夜福利电影| 国产成人精品三上悠亚久久| 人妻精品久久无码专区精东影业| 无码超乳爆乳中文字幕久久 | 91精品免费久久久久久久久| 国产激情久久久久影院小草| 久久婷婷是五月综合色狠狠| 久久人人爽人人爽人人AV东京热| 精品午夜久久福利大片| 一本久久免费视频| 久久亚洲国产中v天仙www| 中文成人久久久久影院免费观看| 久久99国产乱子伦精品免费| 久久艹国产| 精品一区二区久久| 久久亚洲精品人成综合网| 久久青青草原精品国产不卡| 国产日产久久高清欧美一区| 久久久久se色偷偷亚洲精品av| 2020最新久久久视精品爱 | 久久综合色之久久综合| 久久综合狠狠综合久久| 久久久国产视频| 久久人人爽人人爽AV片| 国产99久久久国产精免费| 国产综合久久久久| 亚洲AV日韩AV永久无码久久| 欧美午夜A∨大片久久 | 狠狠综合久久AV一区二区三区| 久久99精品久久久久婷婷| 亚洲AV无码久久寂寞少妇| 久久亚洲熟女cc98cm| 中文字幕精品无码久久久久久3D日动漫| 久久久久四虎国产精品| 一本久久a久久精品综合夜夜| 日韩精品国产自在久久现线拍 |