<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    kooyee ‘s blog

    開源軟件, 眾人努力的結晶, 全人類的共同財富
    posts - 103, comments - 55, trackbacks - 0, articles - 66
       :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    [WEB] MetaData Programme

    Posted on 2007-12-01 20:36 kooyee 閱讀(752) 評論(0)  編輯  收藏 所屬分類: Java

    MetaData Programme

    1.1.        什么是元數據編程

    什么是元數據,元數據就是描述數據的數據(data about data)。最明顯的例子是XML Schema,xml schema就是描述xml的數據,所以它是元數據。另一個例子是數據庫,比如我們可以查詢數據庫中有幾個表,每個表都有什么字段,這些數據就是元數據。Office:office" />

    在開發的世界里,元數據就是能夠綁定到一個類的附加信息,在靜態或者運行時間。JCR175給我們提供annotation就是一種元數據。

    不過在這之前一個我們已經廣泛使用的元數據是XML,如就是EJBXML發布描述符中,你需要定義基于每一個方法的事務屬性。應用服務器指導什么時候,什么地方開始,掛起或者提交一個事務,因為你在BEANXML的配置文件中的元數據內已經定義如方法:RequiredRequiresNew,Support等等,它們綁定在你的EJB類和事務管理之間。XDoclet是另一個元數據的例子。

    1.2.        Annotation的意義和簡單例子

           JDK1.5提供的annotation與我們所常見的classes、fieldssmethods間是什么關系。如下:如果說類和數據成員是名詞,方法是動詞,那么annotation就是形容詞或者副詞,分別描述它們的所具有屬性。

       好,現在就來實現一個annotation

     

    import Java.lang.annotation.Retention;

    package sample.annotation;

    @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)

        
    public @interface Broker {

        String name();

        String address();

        }


    }

     

    使用這個annotation

    Import sample.annotation.broker;

    @Broker(name
    ="anders", address="xiamen")

    public class Agent {

        
    public String getTelPhone (){

            
    return "010-0592-2519280";

        }


    }


    運行期得到這個annotation

    public class Main {

        
    public static void main(String[] args){

    Agent agent 
    = new Agent();

            
    try{

                Annotation[] a 
    = agent.getClass().getMethod("getBrokerName").getAnnotations();

                
    for (int i=0; i<a.length ; i++{

                     
    if( a[i] instanceof Broker){

                          Broker broker 
    = (Broker)a[i];

                         System.out.println(broker.name());

                     }


                 }


            }


            
    catch(Exception e){

                e.printStackTrace(System.out);

            }


       }


    }




    1.3.
            Annotationclass文件格式

           利用sun公司的提供的javap,我們可以看到annotation的在class文件中的表示。以下為對比結果:

    源碼

     

    @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)

    public @interface Broker {

        String name();

        String address();

    }

     

    Javap結果:

    Compiled from "Broker.java"

    interface Broker extends java.lang.annotation.Annotation

     SourceFile: "Broker.java"

     minor version: 0

     major version: 0

     Constant pool:

    const #1 = class    #9; // Broker

    const #2 = class    #10; // Object

    const #3 = class    #11; //Annotation

    const #4 = Asciz    name;

    const #5 = Asciz   ()Ljava/lang/String;;

    const #6 = Asciz    address;

    const #7 = Asciz    SourceFile;

    const #8 = Asciz    Broker.java;

    const #9 = Asciz    Broker;

    const #10 = Asciz   java/lang/Object;

    const #11 = Asciz   java/lang/annotation/Annotation;

    {

    public abstract java.lang.String name();

    public abstract java.lang.String address();

    }  

    源碼:

    @Broker(name="anders", address="xiamen")

    public class Agent {

        
    public String getTelPhone(){

            
    return "0592-2519580";

        }


    }


    Javap結果:

    Compiled from "Agent.java"

    public class Agent extends java.lang.Object

     SourceFile: "Agent.java"

     RuntimeVisibleAnnotations: length = 0x10

       00 01 00 11 00 02 00 12 73 00 13 00 14 73 00 15

      

     minor version: 0

     major version: 0

     Constant pool:

    const #1 = Method   #4.#22;// java/lang/Object."<init>":()V

    const #2 = String   #23;    // 0592-2519580

    const #3 = class    #24;    // Agent

    const #4 = class    #25;    // Object

    const #5 = Asciz    <init>;

    const #6 = Asciz    ()V;

    const #7 = Asciz    Code;

    const #8 = Asciz    LineNumberTable;

    const #9 = Asciz    LocalVariableTable;

    const #10 = Asciz   this;

    const #11 = Asciz   LAgent;;

    const #12 = Asciz   getTelPhone;

    const #13 = Asciz   ()Ljava/lang/String;;

    const #14 = Asciz   SourceFile;

    const #15 = Asciz   Agent.java;

    const #16 = Asciz   RuntimeVisibleAnnotations;

    const #17 = Asciz   LBroker;;

    const #18 = Asciz   name;

    const #19 = Asciz   anders;

    const #20 = Asciz   address;

    const #21 = Asciz   xiamen;

    const #22 = NameAndType#5:#6;// "<init>":()V

    const #23 = Asciz   0592-2519580;

    const #24 = Asciz   Agent;

    const #25 = Asciz   java/lang/Object;

    // 以下為方法域,略  

    補充說明:我們都知道在java 1.0發布時,java class file的格式就已經定下來,要說明的是為了應未來的需要java class file設計了屬性說的機制。一直到J2SE1.4都沒有怎么改變。但這次為了更好的支持metadata技術,一共增加了8個屬性。分別是:

    EnclosingMethodAttribute Anonymous Class Local Inner Class 使用此 Attribute 描述該Class Scope

    Signature AttributeGenerics Class、Method、或 Filed使用此 Attribute 來記錄所要的類型,因為java的范型采用了擦拭法。

    LocalVariableTypeTable Attribute:主要是給 debugger 使用,目的和「LocalVariableTable Attribute類似,只是「LocalVariableTable Attribute 記錄所要的參數表,而「LocalVariableTypeTable Attribute 記錄參數的類型。

    RuntimeVisibleAnnotations Attribute:確定該annotation可以被reflectionAPI返回,適用對象:ClassMethod、Field

    RuntimeInvisibleAnnotations Attribute:確定該annotation無法被reflectionAPI返回,適用對象: Class、MethodField。 

    RuntimeVisibleParameterAnnotations Attribute:同「RuntimeVisibleAnnotations Attribute,適用對象:Method,(該Method 的參數

    RuntimeInvisibleParameterAnnotations Attribute:同「RuntimeInvisibleAnnotations Attribute,適用對象:Method,(該Method 的參數。

    AnnotationDefault Attribute:適用對象:Method,記錄默認值。

    1.4.        為什么需要Annotation

           annotation之前我們已經廣泛使用另外一種元數據xml,為什么需要annotation。Annotationxml的作為元數據的區別是什么——位置。Annotation寫在源代碼中,而xml寫在外部。

           為什么要這樣?如果你開發EJB,你一定為你的EJB寫過xml描述文件。當大量的EJB需要描述時,就出現了所謂的"descriptor hell"。這個也導致了著名的XDoclet的出現。而annotation出現可以避免這種descriptor hell。另外你更改了某個方法為其增加或者減少一個參數,你就對應的修改xml文件,而使用annotation則不必。使用annotation將開發和部署更方便,提供開發效率。

           另外:使用xml的另一個問題是:很多Xml配置太過verbose。相比較EJBHibernate 或者Webwork可以明顯的發現不同。

    1.5.        再議Annotation

    EJB3中,Annotation把開發和部署的工作合在一起。但是在一些企業環境中,開發人員并不控制諸如數據源名等(這些是部署部門和管理部門的工作),這樣把數據源名寫在xml中將比較好。

           Annotation是本身靜態的,一旦添加或者修改annotation都需要重新編譯,在運行時讀取,這樣就喪失了運行時配置的能力。因此Annotations 不會取代xml,它只是提供了另一種途徑。并且我相信sun公司將在未來提供一個方式可以在運行期更改metadata

    關于這點TSS上有著很激烈的討論,很多開發人員提出:利用xml來更改annotation,并希望類似的方式能被采納為標準規范。比如使用如下格式:

     

    <class name="org.hibernate.Item">

    @Entity

        @Table(name="AUCTION_ITEM")

        
    <method sig="getBar()">@Transient</method>

        
    <method sig="doSomething(int, String)">

            @Tx(REQUIRES_NEW)

        
    </method>

    </class>

     

     當然也有不同意見:But then, I think of "overriding" as a different problem to "xml deployment descriptors", and so I think we need two solutions. I think Cedric and Bill are trying to kill two birds with one stone, so maybe their proposals are better....

    關于為annotation提供動態配置能力的問題,其中一個網友認為:Sun make it real pain to do the deployment XML so that they can introduce annotation to fix it. The annotation can make code/deployment coupling so strong that Sun can come out with a new way (annotation interceptor in jdk 1.6? :)) for fixing it. and the cycles goes on...這讓我想起了類似的現象:JSPTagLib。希望Annotation不會和TagLib有同樣的命運。

           Annotation本身引入另一種類型的接口。在EJB3中確實使程序更加POJO,也消除了一些接口。并且編譯后的代碼也可以直接移植到另一個并不處理這些annotations的環境中(感謝VM在加載類時并不檢查那些annotationsclasses,甚至這些類不在classpath中)。然而代碼也確實增加了另一些接口。這個表現在編譯期,如果沒有這些annotation classes,是編譯不過的。

           另一個問題(還好不算很重要),關于annotationnamespace。在多層應用的系統中,可能會出現同樣的全局annotationnamespace沖突。比如一些公共的annotation,如@Transaction,將會被應用在很多個層次中。盡量讓namespace長些,可以避免這個問題。

    1.6.        元數據編程的應用:

    Annotation已經被集成到很多的java規范和標準中,很重要的是它已經被J2EE標準,如EJB3所采用,當然也被許多開源的組件體系如:ASPectJ。

           Annotation最重要的應用將是AOP:由于annotation可以天然的表示系統中的另一個橫切面,同時Annotation的識別是通過反射得到的,所以Annotation很自然的應用到基于動態代理的AOP實現。AOPAlliance也支持metadata handling。AspectJ也發布了基于annotation的新版本。

           在實現AOP上,使用annotation也比使用XML有一個優勢:如前所述,annotation更像是形容詞和副詞,這樣比較不容易verbose。當然這個是相對的,在實際的實現中更依賴開發人員的努力。

           這里,筆者將展示一個不完整也不成熟的基于annotationAOP例子代碼——關于銀行卡的例子。

           功能需求:銀行卡業務分為轉帳,查詢余額,查詢明細,POS消費等。這其中轉帳和POS消費是要收費的(轉帳收取的是用戶的手續費,而POS消費收取的是商家的手續費),另外POS消費還可能有積分的(比如筆者的牡丹貸記卡)。消費轉帳都要記錄明細。但查詢余額就不需要記錄在明細中。

           代碼如下(在這個例子沒有用動態代理也沒有用已有的AOP框架,使代碼看起來簡單些)

      1// 銀行卡對象
      2
      3public class Card {
      4
      5    private String account; 
      6
      7//some field method
      8
      9}

     10
     11Annotation:
     12
     13// 手續費
     14
     15// type= "user", 表示收取用戶手續費; type= "Biz", 表示收取商家手續費
     16
     17public @interface Fee{
     18
     19    String type();
     20
     21}

     22
     23// 積分
     24
     25public @interface Index {
     26
     27}

     28
     29// 記錄明細
     30
     31public @interface BizLog {
     32
     33}

     34
     35// 事務處理
     36
     37public @interface Transaction {
     38
     39}

     40
     41// 業務接口
     42
     43public interface BizAction {
     44
     45    void execute(Card card, RunData rundata);
     46
     47}

     48
     49// 轉帳業務
     50
     51@Fee(type="user")
     52
     53@Transaction
     54
     55@BizLog
     56
     57public class TransferAction implements BizAction {
     58
     59    public void execute(Card card, RunData rundata) {
     60
     61        //To change body of implemented methods use File | Settings | File Templates.
     62
     63    }

     64
     65}

     66
     67// POS消費
     68
     69@Fee(type="Biz")
     70
     71@Transaction
     72
     73@BizLog
     74
     75@Index
     76
     77public class POSAction implements BizAction {
     78
     79    public void execute(Card card, RunData rundata) {
     80
     81        //To change body of implemented methods use File | Settings | File Templates.
     82
     83    }

     84
     85}

     86
     87// 查詢明細
     88
     89public class QueryDetail implements BizAction {    
     90
     91    public void execute(Card card, RunData rundata) {
     92
     93        //To change body of implemented methods use File | Settings | File Templates.
     94
     95    }

     96
     97}

     98
     99// 業務操作監視器接口
    100
    101public interface BizActionMonitor {
    102
    103   void execute(BizAction action, RunData rundata);
    104
    105}

    106
    107// 業務操作監視器實現
    108
    109public class BizActionMonitorImpl implements BizActionMonitor{
    110
    111    public void execute(BizAction action, RunData rundata) {
    112
    113        Annotation[] annotations = action.getClass().getAnnotations();
    114
    115        for(Annotation annotation : annotations){
    116
    117            if (annotation instanceof Fee)// 計算手續費   }
    118
    119            if (annotation instanceof Index)//計算積分    }
    120
    121            if (annotation instanceof Transaction)// 準備事務 }
    122
    123            if (annotation instanceof BizLog)// 記錄明細   }
    124
    125        }

    126
    127    }

    128
    129}

    130
    131// 控制器對象
    132
    133public class controller{
    134
    135    private BizActionMonitor monitor;   
    136
    137    public void execute(BizActionUI, rundata){
    138
    139        BizAction action = getAction(BizActionUI);      
    140
    141        monitor.execute(action, rundata);
    142
    143    }

    144
    145}

    146
    147// 運行時數據
    148
    149public interface RunData {
    150
    151   // some method
    152
    153}

    154
    155// 用戶設備(POS機, ATM或者柜臺終端)接口
    156
    157public class BizActionUI {
    158
    159      private RunData rundata;
    160
    161      private Controller controller;
    162
    163      public BizActionUI(RunData rundata, Controller controller){
    164
    165          this.rundata = rundata;
    166
    167          this.controller = controller;
    168
    169      }

    170
    171      public void execute()// 某個子類實現 }
    172
    173      public void commit(){
    174
    175          controller.execute(this, rundata);
    176
    177      }

    178
    179}

    180
    181public class Main{
    182
    183    private Rundata rundata;
    184
    185    private Controller controller; 
    186
    187    public populateUI(command){
    188
    189        BizActionUI ui = getUI(command);
    190
    191        ui.execute();
    192
    193    }
       
    194
    195    public BizActionUI getUI(command){
    196
    197        //
    198
    199        BizActionUI ui 
    200
    201        if//.){
    202
    203            ui = new SomeBizActionUI(rundata, controller);
    204
    205        }

    206
    207        return ui;      
    208
    209    }
        
    210
    211    public static main(String[] args){
    212
    213        //
    214
    215        Main main = new Main();
    216
    217        main.populateUI(command)
    218
    219        //
    220
    221    }

    222
    223}

    224
    225

    1.7.
            結束語:

    本文討論了annotation技術,展示了annotationclass文件格式,并討論了annotation技術本身的優勢和不足,并于現有的xml技術加以比較,展望了annotation技術的應用前景AOP

    限于筆者自身的水平(包括技術水平和寫作水平),技術上對annotation的學習比較有限,寫作上也感覺好多話無法用文字來表達,因而本文的代碼會比較多(大概有一半以上)。

    主站蜘蛛池模板: 少妇中文字幕乱码亚洲影视| 亚洲日韩精品无码专区加勒比☆| 亚洲国产一区二区三区| 大陆一级毛片免费视频观看 | 久久精品国产亚洲AV香蕉| 在线观看午夜亚洲一区| 在线亚洲精品自拍| 中文字幕亚洲无线码| 亚洲色偷拍区另类无码专区| 久久久久国产亚洲AV麻豆| 亚洲精品tv久久久久| 亚洲精品无码久久久久去q | 人妻视频一区二区三区免费| 成人免费一区二区无码视频| 成年美女黄网站18禁免费| 免费观看的a级毛片的网站| 国产免费一区二区三区VR| 亚洲XX00视频| 亚洲精品无码久久久影院相关影片 | 香港一级毛片免费看| 黄页免费视频播放在线播放| 国产成人精品免费大全| 99在线热播精品免费99热| 91福利免费体验区观看区| 国产免费一区二区三区| 在线成人a毛片免费播放| 亚洲国产成人久久综合区| 亚洲日韩激情无码一区| 久久亚洲精品无码aⅴ大香| 亚洲日本VA午夜在线影院| 国产亚洲综合久久| 国产免费久久久久久无码| 999久久久免费精品播放| 国产精品免费观看久久| 亚洲日韩国产成网在线观看| 亚洲av成人无码久久精品| 亚洲国产综合自在线另类| 国产精品亚洲专区无码牛牛| a毛片免费全部播放完整成| h片在线免费观看| 国产无遮挡裸体免费视频|