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

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

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

    拾貝殼

    走過的路
    隨筆 - 39, 文章 - 1, 評論 - 14, 引用 - 0
    數據加載中……

    Ten Reasons Why Blogging is Good For Your Career

    1. You have to get noticed to get promoted.

    2. You have to get noticed to get hired.

    3. It really impresses people when you say “Oh, I’ve written about that, just google for XXX and I’m on the top page” or “Oh, just google my name.”

    4. No matter how great you are, your career depends on communicating. The way to get better at anything, including communication, is by practicing. Blogging is good practice.

    5. Bloggers are better-informed than non-bloggers. Knowing more is a career advantage.

    6. Knowing more also means you’re more likely to hear about interesting jobs coming open.

    7. Networking is good for your career. Blogging is a good way to meet people.

    8. If you’re an engineer, blogging puts you in intimate contact with a worse-is-better 80/20 success story. Understanding this mode of technology adoption can only help you.

    9. If you’re in marketing, you’ll need to understand how its rules are changing as a result of the current whirlwind, which nobody does, but bloggers are at least somewhat less baffled.

    10. It’s a lot harder to fire someone who has a public voice, because it will be noticed.

      from http://www.tbray.org/ongoing/When/200x/2005/03/08/BloggingIsGood

    posted @ 2006-06-16 15:25 binge 閱讀(313) | 評論 (0)編輯 收藏

    JAVA開發者應該去的20個英文網站

    http://www.javaalmanac.com

    ??? Java開發者年鑒一書的在線版本. 要想快速查到某種Java技巧的用法及示例代碼, 這是一個不錯的去處.

    http://www.onjava.com

    ??? O'Reilly的Java網站. 每周都有新文章

    http://java.sun.com

    ??? 官方的Java開發者網站 - 每周都有新文章發表

    http://www.developer.com/java

    ??? 由Gamelan.com 維護的Java技術文章網站

    http://www.java.net

    ??? Sun公司維護的一個Java社區網站

    http://www.builder.com

    ??? Cnet的Builder.com網站 - 所有的技術文章, 以Java為主.

    http://www.ibm.com/developerworks/java

    ??? IBM的Developerworks技術網站; 這是其中的Java技術主頁

    http://www.javaworld.com

    ??? 最早的一個Java站點. 每周更新Java技術文章

    http://www.devx.com/java

    ??? DevX維護的一個Java技術文章網站

    http://www.fawcette.com/javapro

    ??? JavaPro在線雜志網站.

    http://www.sys-con.com/java

    ??? Java Developers Journal的在線雜志網站.

    http://www.javadesktop.org

    ??? 位于Java.net的一個Java桌面技術社區網站.

    http://www.theserverside.com

    ??? 這是一個討論所有Java服務器端技術的網站.

    http://www.jars.com

    ??? 提供Java評論服務. 包括各種framework和應用程序

    http://www.jguru.com

    ??? 一個非常棒的采用Q&A形式的Java技術資源社區.

    http://www.javaranch.com

    ???? 一個論壇,得到Java問題答案的地方,初學者的好去處。

    http://www.ibiblio.org/javafaq/javafaq.html

    ??? comp.lang.java的FAQ站點 - 收集了來自comp.lang.java新聞組的問題和答案的分類目錄.

    http://java.sun.com/docs/books/tutorial/

    ??? 來自SUN公司的官方Java指南 - 對于了解幾乎所有的java技術特性非常有幫助.

    http://www.javablogs.com

    ??? 互聯網上最活躍的一個Java Blog網站.

    http://java.about.com/

    轉自51cto

    posted @ 2006-06-16 14:11 binge 閱讀(788) | 評論 (0)編輯 收藏

    JTA和JDBC事務

     一般情況下,J2EE應用服務器支持JDBC事務、JTA事務、容器管理事務。這里討論JTA和JDBC事務的區別。這2個是常用的DAO模式事務界定方式。
    JDBC 事務
     JDBC 事務是用 Connection 對象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務模式:自動提交和手工提交。
    ★ 在jdbc中,事務操作缺省是自動提交。也就是說,一條對數據庫的更新表達式代表一項事務操作,操作成功后,系統將自動調用commit()來提交,否則將調用rollback()來回滾。
    ★ 在jdbc中,可以通過調用setAutoCommit(false)來禁止自動提交。之后就可以把多個數據庫操作的表達式作為一個事務,在操作完成后調用commit()來進行整體提交,倘若其中一個表達式操作失敗,都不會執行到commit(),并且將產生響應的異常;此時就可以在異常捕獲時調用rollback()進行回滾。這樣做可以保持多次更新操作后,相關數據的一致性,示例如下:

        try {

    conn = 

    DriverManager.getConnection    

    (&quot;jdbc:oracle:thin:@host:1521:SID&quot;,&quot;username&quot;,&quot;userpwd&quot;;

           conn.setAutoCommit(false);//禁止自動提交,設置回滾點

           stmt = conn.createStatement();

    stmt.executeUpdate(“alter table …”); //數據庫更新操作1

    stmt.executeUpdate(“insert into table …”); //數據庫更新操作2

           conn.commit(); //事務提交

         }catch(Exception ex) {    

             ex.printStackTrace();

             try {

              conn.rollback(); //操作不成功則回滾

              }catch(Exception e) {

    e.printStackTrace();

               }

    }

     JDBC 事務的一個缺點是事務的范圍局限于一個數據庫連接。一個 JDBC 事務不能跨越多個數據庫。
    JTA事務
     JTA(Java Transaction API) 為 J2EE 平臺提供了分布式事務服務。
     要用 JTA 進行事務界定,應用程序要調用 javax.transaction.UserTransaction 接口中的方法。例如:
     utx.begin();
          // ...
          DataSource ds = obtainXADataSource();
          Connection conn = ds.getConnection();
          pstmt = conn.prepareStatement("UPDATE MOVIES ...");
          pstmt.setString(1, "Spinal Tap");
          pstmt.executeUpdate();
          // ...
          utx.commit();

     讓我們來關注下面的話:
     “用 JTA 界定事務,那么就需要有一個實現 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅動程序。一個實現了這些接口的驅動程序將可以參與 JTA 事務。一個 XADataSource 對象就是一個 XAConnection 對象的工廠。 XAConnection s 是參與 JTA 事務的 JDBC 連接。”
     要使用JTA事務,必須使用XADataSource來產生數據庫連接,產生的連接為一個XA連接。
     XA連接(javax.sql.XAConnection)和非XA(java.sql.Connection)連接的區別在于:XA可以參與JTA的事務,而且不支持自動提交。
         Note:
    Oracle, Sybase, DB2, SQL Server等大型數據庫才支持XA, 支持分布事務。
    My SQL 連本地都支持不好,更別說分布事務了。
    JTA方式的實現過程
       用XADataSource產生的XAConnection它擴展了一個getXAResource()方法,事務通過這個方法把它加入到事務容器中進行管理.對于調用者來說,根本看不到事務是如果管理的,你只要聲明開始事務,告訴容器我下面的操作要求事務參與了,最后告訴事務說到這兒可以提交或回滾了,別的都是黑箱操作。
     在使用JTA之前,你必須首先實現一個Xid類用來標識事務(在普通情況下這將由事務管理程序來處理)。Xid包含三個元素:formatID、gtrid(全局事務標識符)和bqual(分支修飾詞標識符)。
     下面的例子說明Xid的實現:

    import javax.transaction.xa.*;
    public class MyXid implements Xid
    {
     protected int formatId;
     protected byte gtrid[];
     protected byte bqual[];
     public MyXid()
     {
     }
     public MyXid(int formatId, byte gtrid[], byte bqual[])
     {
      this.formatId = formatId;
      this.gtrid = gtrid;
      this.bqual = bqual;
     }

     public int getFormatId()
     {
      return formatId;
     }

     public byte[] getBranchQualifier()
     {
      return bqual;
     }

     public byte[] getGlobalTransactionId()
     {
      return gtrid;
     }

    }
     其次,你需要創建一個你要使用的數據庫的數據源:

    public DataSource getDataSource()
     throws SQLException
     {
      SQLServerDataSource xaDS = new
      com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource();
      xaDS.setDataSourceName("SQLServer");
      xaDS.setServerName("server");
      xaDS.setPortNumber(1433);
      xaDS.setSelectMethod("cursor");
      return xaDS;
    }

      例1?這個例子是用“兩步提交協議”來提交一個事務分支:

    XADataSource xaDS;
    XAConnection xaCon;
    XAResource xaRes;
    Xid xid;
    Connection con;
    Statement stmt;
    int ret;
    xaDS = getDataSource();
    xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password");
    xaRes = xaCon.getXAResource();
    con = xaCon.getConnection();
    stmt = con.createStatement();
    xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02});
    try {
      xaRes.start(xid, XAResource.TMNOFLAGS);
      stmt.executeUpdate("insert into test_table values (100)");
      xaRes.end(xid, XAResource.TMSUCCESS);
      ret = xaRes.prepare(xid);
      if (ret == XAResource.XA_OK) {
        xaRes.commit(xid, false);
       }
    }
    catch (XAException e) {
     e.printStackTrace();
    }
    finally {
     stmt.close();
     con.close();
     xaCon.close();
    }
     當然,實際過程中,我們不需要寫這些代碼,這些代碼是JTA最終的實現代碼。
    關于“兩步提交協議”,可以參看下面的文章:
    http://www.jspcn.net/htmlnews/11049371131251752.html

     http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html


    選擇最好的方式
    用 JDBC API 進事務界定來構建 DAO 類的。這些 DAO 類可以總結如下:

    事務界定代碼嵌入在 DAO 類中。
    DAO 類使用 JDBC API 進行事務界定。
    調用者不能界定事務。
    事務范圍局限于單個 JDBC 連接。
    JDBC 事務并不總是適合復雜的企業應用程序。如果您的事務要跨越多個 DAO 或者多個數據庫,那么下列實現策略也許更合適:

    事務用 JTA 界定。
    事務界定代碼從 DAO 中分離出來。
    調用者負責界定事務。
    DAO 加入一個全局事務。
    JDBC 方式由于其簡單性而具有吸引力,JTA 方式提供了更大的靈活性。您所選擇的實現將取決于應用程序的特定需求。
    XADataSource例子:
    <?xml version="1.0" encoding="UTF-8"?>

    <!-- ===================================================================== -->
    <!--    -->
    <!--  JBoss Server Configuration    -->
    <!-- Thanks to Horia Muntean <horia@bvb.ro>   -->
    <!-- ===================================================================== -->

    <!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ -->


    <datasources>
       <!--
           XADatasource for DB2 V8.1 (app driver)
           copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib
       -->

       <xa-datasource>
         <jndi-name>DB2XADS</jndi-name>
         <xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class>
         <xa-datasource-property name="DatabaseName">yout_database_name</xa-datasource-property>
         <xa-datasource-property name="User">your_user</xa-datasource-property>
         <xa-datasource-property name="Password">your_password</xa-datasource-property>
       </xa-datasource>
    </datasources>

    引用:
     http://www.jspcn.net/htmlnews/11049371131251752.html
    http://www-128.ibm.com/developerworks/cn/java/j-dao/
    http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html

     

    posted @ 2006-06-15 15:53 binge 閱讀(5209) | 評論 (1)編輯 收藏

    JMS初讀

    33.2 基本的jms api概念
    ?? 33.2.1 jms api體系結構
    ???? jms應用程序組成部分:
    ????a. jms提供者--------j2ee平臺.
    ??? b.jms客戶端--------需要用戶完成的應用程序.
    ??? c.消息----在客戶端之間傳遞信息的對象
    ?? d.管理的對象----連接工廠和目的地
    ?33.2.2 消息域
    ???分為"點到點消息傳遞域"和"發表/訂閱小心傳遞域"
    ?33.2.3 消費消息
    ???兩種方式:同步和異步.同步直接用receive方法提取消息.異步需要可湖段為消費者注冊一個見聽器.通過調用見聽器的onMessage方法來分發消息.
    33.3 jms api編程模型
    ? 33.3.1 管理的對象
    ?? a.連接工廠
    ??? 通常是執行jndi查找獲得連接工廠.eg:
    ? Context ctx= new InitialContext();
    ? ConnectionFactory cf=(ConnectionFactory )?ctx.lookup("jms/QueueConnectionFactory");
    ConnectionFactory cf=(ConnectionFactory )?ctx.lookup("jms/TopicConnectionFactory");
    ?b.目的地
    ?? 在ptp中,目的地是"隊列".在發表/訂閱中,目的地是"主題".
    ? eg:
    Destination mydest=(Topic)ctx.lookup("jms/mytopic");
    33.3.2 連接
    ?連接由連接工廠來創建.eg:
    Connection conn=ConnectionFactory .createConnection();
    33.3.3 會話
    會話 由 Connection來創建
    Session session=Connection.createSession(false,Session.AUTO_ACKOWLEDGE);
    事務性的會話
    Session session=Connection.createSession(true,0);
    33.3.4 消息生產者
    由session 來創建,實現MessageProducer接口.
    ?? MessageProducer mp=session.createProducer(myQueue);
    發送動作
    mp.send(message);
    33.3.5 消息消費者
    ?由session創建,實現MessageConsumer接口.
    eg:
    MessageConsumer mc=session.createConsumer(myQueue);
    bwt:
    利用session.createDurableSubscriber可以創建長期的訂閱者.
    ? ========獲得消息==
    同步方式.
    connection.start();
    Message m=consumer.receive();
    connection.start();
    Message m=consumer.receive(1000); //time out afer a second
    異步方式.
    構造一個消息艦艇器,用setMessageListener方法向具體的MessageConsumer中注冊.eg:
    ? Listener myListener= new Listener ();
    consumer.setMessageListener (myListener );
    33.3.6 消息
    分為消息頭,消息屬性和消息體,只有消息頭是必須的.
    消息頭存放了可護短和提供者用來識別和路由消息的值.
    常見的消息體的格式(消息類型)有5種.
    ?
    ?

    posted @ 2006-05-31 22:25 binge 閱讀(428) | 評論 (0)編輯 收藏

    [轉]一篇不錯的講解Java異常的文章

    六種異常處理的陋習

      你覺得自己是一個Java專家嗎?是否肯定自己已經全面掌握了Java的異常處理機制?在下面這段代碼中,你能夠迅速找出異常處理的六個問題嗎?

      1 OutputStreamWriter out = ...

      2 java.sql.Connection conn = ...

      3 try { // ⑸

      4  Statement stat = conn.createStatement();

      5  ResultSet rs = stat.executeQuery(

      6   "select uid, name from user");

      7  while (rs.next())

      8  {

      9   out.println("ID:" + rs.getString("uid") // ⑹

      10    ",姓名:" + rs.getString("name"));

      11  }

      12  conn.close(); // ⑶

      13  out.close();

      14 }

      15 catch(Exception ex) // ⑵

      16 {

      17  ex.printStackTrace(); //⑴,⑷

      18 }

      作為一個Java程序員,你至少應該能夠找出兩個問題。但是,如果你不能找出全部六個問題,請繼續閱讀本文。

      本文討論的不是Java異常處理的一般性原則,因為這些原則已經被大多數人熟知。我們要做的是分析各種可稱為“反例”(anti-pattern)的違背優秀編碼規范的常見壞習慣,幫助讀者熟悉這些典型的反面例子,從而能夠在實際工作中敏銳地察覺和避免這些問題。

      反例之一:丟棄異常

      代碼:15行-18行。

      這段代碼捕獲了異常卻不作任何處理,可以算得上Java編程中的殺手。從問題出現的頻繁程度和禍害程度來看,它也許可以和C/C++程序的一個惡名遠播的問題相提并論??不檢查緩沖區是否已滿。如果你看到了這種丟棄(而不是拋出)異常的情況,可以百分之九十九地肯定代碼存在問題(在極少數情況下,這段代碼有存在的理由,但最好加上完整的注釋,以免引起別人誤解)。

      這段代碼的錯誤在于,異常(幾乎)總是意味著某些事情不對勁了,或者說至少發生了某些不尋常的事情,我們不應該對程序發出的求救信號保持沉默和無動于衷。調用一下printStackTrace算不上“處理異常”。不錯,調用printStackTrace對調試程序有幫助,但程序調試階段結束之后,printStackTrace就不應再在異常處理模塊中擔負主要責任了。

      丟棄異常的情形非常普遍。打開JDK的ThreadDeath類的文檔,可以看到下面這段說明:“特別地,雖然出現ThreadDeath是一種‘正常的情形’,但ThreadDeath類是Error而不是Exception的子類,因為許多應用會捕獲所有的Exception然后丟棄它不再理睬。”這段話的意思是,雖然ThreadDeath代表的是一種普通的問題,但鑒于許多應用會試圖捕獲所有異常然后不予以適當的處理,所以JDK把ThreadDeath定義成了Error的子類,因為Error類代表的是一般的應用不應該去捕獲的嚴重問題。可見,丟棄異常這一壞習慣是如此常見,它甚至已經影響到了Java本身的設計。

      那么,應該怎樣改正呢?主要有四個選擇:

      1、處理異常。針對該異常采取一些行動,例如修正問題、提醒某個人或進行其他一些處理,要根據具體的情形確定應該采取的動作。再次說明,調用printStackTrace算不上已經“處理好了異常”。

      2、重新拋出異常。處理異常的代碼在分析異常之后,認為自己不能處理它,重新拋出異常也不失為一種選擇。

      3、把該異常轉換成另一種異常。大多數情況下,這是指把一個低級的異常轉換成應用級的異常(其含義更容易被用戶了解的異常)。

      4、不要捕獲異常。

      結論一:既然捕獲了異常,就要對它進行適當的處理。不要捕獲異常之后又把它丟棄,不予理睬。

      反例之二:不指定具體的異常

      代碼:15行。

      許多時候人們會被這樣一種“美妙的”想法吸引:用一個catch語句捕獲所有的異常。最常見的情形就是使用catch(Exception ex)語句。但實際上,在絕大多數情況下,這種做法不值得提倡。為什么呢?

      要理解其原因,我們必須回顧一下catch語句的用途。catch語句表示我們預期會出現某種異常,而且希望能夠處理該異常。異常類的作用就是告訴Java編譯器我們想要處理的是哪一種異常。由于絕大多數異常都直接或間接從java.lang.Exception派生,catch(Exception ex)就相當于說我們想要處理幾乎所有的異常。

      再來看看前面的代碼例子。我們真正想要捕獲的異常是什么呢?最明顯的一個是SQLException,這是JDBC操作中常見的異常。另一個可能的異常是IOException,因為它要操作OutputStreamWriter。顯然,在同一個catch塊中處理這兩種截然不同的異常是不合適的。如果用兩個catch塊分別捕獲SQLException和IOException就要好多了。這就是說,catch語句應當盡量指定具體的異常類型,而不應該指定涵蓋范圍太廣的Exception類。

      另一方面,除了這兩個特定的異常,還有其他許多異常也可能出現。例如,如果由于某種原因,executeQuery返回了null,該怎么辦?答案是讓它們繼續拋出,即不必捕獲也不必處理。實際上,我們不能也不應該去捕獲可能出現的所有異常,程序的其他地方還有捕獲異常的機會??直至最后由JVM處理。

      結論二:在catch語句中盡可能指定具體的異常類型,必要時使用多個catch。不要試圖處理所有可能出現的異常。

      反例之三:占用資源不釋放

      代碼:3行-14行。

      異常改變了程序正常的執行流程。這個道理雖然簡單,卻常常被人們忽視。如果程序用到了文件、Socket、JDBC連接之類的資源,即使遇到了異常,也要正確釋放占用的資源。為此,Java提供了一個簡化這類操作的關鍵詞finally。

      finally是樣好東西:不管是否出現了異常,Finally保證在try/catch/finally塊結束之前,執行清理任務的代碼總是有機會執行。遺憾的是有些人卻不習慣使用finally。

      當然,編寫finally塊應當多加小心,特別是要注意在finally塊之內拋出的異常??這是執行清理任務的最后機會,盡量不要再有難以處理的錯誤。

      結論三:保證所有資源都被正確釋放。充分運用finally關鍵詞。

      反例之四:不說明異常的詳細信息

      代碼:3行-18行。

      仔細觀察這段代碼:如果循環內部出現了異常,會發生什么事情?我們可以得到足夠的信息判斷循環內部出錯的原因嗎?不能。我們只能知道當前正在處理的類發生了某種錯誤,但卻不能獲得任何信息判斷導致當前錯誤的原因。

      printStackTrace的堆棧跟蹤功能顯示出程序運行到當前類的執行流程,但只提供了一些最基本的信息,未能說明實際導致錯誤的原因,同時也不易解讀。

      因此,在出現異常時,最好能夠提供一些文字信息,例如當前正在執行的類、方法和其他狀態信息,包括以一種更適合閱讀的方式整理和組織printStackTrace提供的信息。

      結論四:在異常處理模塊中提供適量的錯誤原因信息,組織錯誤信息使其易于理解和閱讀。

      反例之五:過于龐大的try塊

      代碼:3行-14行。

      經常可以看到有人把大量的代碼放入單個try塊,實際上這不是好習慣。這種現象之所以常見,原因就在于有些人圖省事,不愿花時間分析一大塊代碼中哪幾行代碼會拋出異常、異常的具體類型是什么。把大量的語句裝入單個巨大的try塊就象是出門旅游時把所有日常用品塞入一個大箱子,雖然東西是帶上了,但要找出來可不容易。

      一些新手常常把大量的代碼放入單個try塊,然后再在catch語句中聲明Exception,而不是分離各個可能出現異常的段落并分別捕獲其異常。這種做法為分析程序拋出異常的原因帶來了困難,因為一大段代碼中有太多的地方可能拋出Exception。
    結論五:盡量減小try塊的體積。

      反例之六:輸出數據不完整

      代碼:7行-11行。

      不完整的數據是Java程序的隱形殺手。仔細觀察這段代碼,考慮一下如果循環的中間拋出了異常,會發生什么事情。循環的執行當然是要被打斷的,其次,catch塊會執行??就這些,再也沒有其他動作了。已經輸出的數據怎么辦?使用這些數據的人或設備將收到一份不完整的(因而也是錯誤的)數據,卻得不到任何有關這份數據是否完整的提示。對于有些系統來說,數據不完整可能比系統停止運行帶來更大的損失。

      較為理想的處置辦法是向輸出設備寫一些信息,聲明數據的不完整性;另一種可能有效的辦法是,先緩沖要輸出的數據,準備好全部數據之后再一次性輸出。

      結論六:全面考慮可能出現的異常以及這些異常對執行流程的影響。

      改寫后的代碼

      根據上面的討論,下面給出改寫后的代碼。也許有人會說它稍微有點?嗦,但是它有了比較完備的異常處理機制。

      OutputStreamWriter out = ...

      java.sql.Connection conn = ...

      try {

      Statement stat = conn.createStatement();

      ResultSet rs = stat.executeQuery(

      "select uid, name from user");

      while (rs.next())

      {

      out.println("ID:" + rs.getString("uid") + ",姓名: " + rs.getString("name"));

      }

      }

      catch(SQLException sqlex)

      {

      out.println("警告:數據不完整");

      throw new ApplicationException("讀取數據時出現SQL錯誤", sqlex);

      }

      catch(IOException ioex)

      {

      throw new ApplicationException("寫入數據時出現IO錯誤", ioex);

      }

      finally

      {

      if (conn != null) {

      try {

       conn.close();

      }

      catch(SQLException sqlex2)

      {

       System.err(this.getClass().getName() + ".mymethod - 不能關閉數據庫連接: " + sqlex2.toString());

      }

      }

      if (out != null) {

      try {

       out.close();

      }

      catch(IOException ioex2)

      {

      System.err(this.getClass().getName() + ".mymethod - 不能關閉輸出文件" + ioex2.toString());

      }

      }

      }


      本文的結論不是放之四海皆準的教條,有時常識和經驗才是最好的老師。如果你對自己的做法沒有百分之百的信心,務必加上詳細、全面的注釋。

      另一方面,不要笑話這些錯誤,不妨問問你自己是否真地徹底擺脫了這些壞習慣。即使最有經驗的程序員偶爾也會誤入歧途,原因很簡單,因為它們確確實實帶來了“方便”。所有這些反例都可以看作Java編程世界的惡魔,它們美麗動人,無孔不入,時刻誘惑著你。也許有人會認為這些都屬于雞皮蒜毛的小事,不足掛齒,但請記住:勿以惡小而為之,勿以善小而不為。

    posted @ 2006-05-31 22:20 binge 閱讀(308) | 評論 (0)編輯 收藏

    Commons Configuration

         摘要: Configuration 簡介 ?Configuration 的參數可能來自下面的資源: ??? *? Properties files??? * XML documents??? * Property list files (.plist)??? * JNDI??? * JDBC Datasource??? * System prope...  閱讀全文

    posted @ 2006-05-31 10:30 binge 閱讀(2962) | 評論 (0)編輯 收藏

    Commons Lang

    官方地址:http://jakarta.apache.org/commons/lang/

    概述:
    ???標準的java庫并沒有提供足夠的處理他的核心類的方法,Lang組件提供了這些擴展的方法
    ???lang 組件為java.lang API提供了一套幫助類。特別是String處理方法,基本的數字處理方法,對象反射,創建和序列化和系統屬性。另外他包含了一個可繼承的
    enum類型,一個exception結構,對java.util.Date的基本加強以及一系列構建方法,比如hashCode,toString和equals
    可以點擊下面的連接獲得體驗:
    http://www.j2medev.com/bbs/dispbbs.asp?boardid=3&id=3835&star=1&page=3

    http://www.sentom.net/list.asp?id=76
    ??
    lang.*
    ????String字符串處理-StringUtils,StringEscapeUtils,RondomStringUtils,Tokenizer,WordUtils.
    ??? RandomStringUtils 顧名思義,它提供了一段文本,常用來做默認密碼的值。 StringEscapeUtils 包含了escape和unescape "java,javascript,html,xml和sql"的方法。 Tokenizer 是java.util.StringTokenizer的改良。
    ?? 另外,WordUtils是另一個String處理類。他在String的單詞層次上工作,比如,WordUtils.capitalize方法會將一段文本中的每個單詞都首字母大寫。WordUtils也包含了包裝文本的方法。
    ???字符處理- CharSetUtils, CharSet, CharRange, CharUtils
    字符的處理也很重要,CharUtils因此而存在。CharSetUtils則是為了對字符串作批處理。注意,盡管CharSetUtils接受一個String參數,但卻把它當成一組字符。比如:CharSetUtils.delete("testtest", "tr")將刪除所有的t和所有的r,而不僅僅是tr這個字符串。
    CharRange和CharSet是CharSetUtils內部將要用到的類。
    JVM交互-SystemUtils, CharEncoding
    SystemUtils是個很小的類,他將使你獲得你的JVM平臺信息變得更為簡單。比如:SystemUtils.isJavaVersionAtLeast(1.3f) 。CharEncoding也是被用來做和jvm的交互,可能會被用來查看特定的環境上支持那種字符編碼。
    序列化-SerializationUtils, SerializationException
    ?序列化并不難!一個簡單的工具類就可以刈除你的痛苦。而且,他提供一個方法通過反序列化和重序列化來克隆對象,這是個很老的java訣竅。
    Assorted functions -ObjectUtils,ClassUtils,ArrayUtils,BooleanUtils
    ? ObjectUtils提供了許多對對象便利的操作,以及大部分的對java.lang.Object的方法的null-safe實現。
    ???ClassUtils提供了一套用于反射的幫助函數。值得留意的是在ClassUtils隱含的comparators,他可以對Class和package按名稱進行排序。這個排序僅僅是字典排序。
    ???接下來,我們介紹ArrayUtils.他有很多方法和這些方法的重載方法。這個類值得我們深入的了解一下。開始之前,我們假設所有的被提及的方法都被重載(無論是基本類型還是對象類型)。而且,‘xxx’代表了一個基本類型,有時候也包含了對象。
    • ArrayUtils 為基本類型提供了一個單態的空疏組.這些將被Collections API的toArray()方法中用到, 也可以在用在那些希望在發生錯誤時返回空數組的方法中.
    • add(xxx[], xxx) 添加一個原始類型到一個數組, 自動調整數組的大小. 對象類型可以用.
    • clone(xxx[]) 克隆一個基本類型或者對象數組.
    • contains(xxx[], xxx) 在一個基本類型或者對象類型的數組中查找一個基本類型或者對象類型.
    • getLength(Object) 返回一個數組的大小.如果參數不是一個數組,將會返回一個IllegalArgumentException異常。
    • ?hashCode(Object), equals(Object, Object), toString(Object)
    • indexOf(xxx[], xxx)indexOf(xxx[], xxx, int) 是仿照String的相關方法,?但是他用來處理primitive/Object數組.?另外,?lastIndexOf?系列的方法也存在.
    • isEmpty(xxx[]) 判斷一個數組是否為null或者空.
    • isSameLength(xxx[], xxx[]) 判斷2個數組的大小是否相等.
    • 除了添加的方法,?這里也提供了2類刪除的方法.?第一種是根據索引刪除:remove(xxx[], int),?第二種刪除數組中的第一個值:remove(xxx[], xxx).?
    • ?reverse(xxx[])?翻轉一個數組.
    • The subarray(xxx[], int, int) 取出一個大數組的一部分.
    • 基本類型和基本類型的包裝類之間的轉換可以通過 toObject(xxx[])toPrimitive(Xxx[]) 方法.
    ???ArrayUtils.toMap(Object[])用來將一個數組轉化為一個map,比如:
    ?????? Map colorMap = MapUtils.toMap(new String[][] {{
    ?????????? {"RED", "#FF0000"},
    ?????????? {"GREEN", "#00FF00"},
    ?????????? {"BLUE", "#0000FF"}
    ?????? });
    ???? BooleanUtils,對這個類,或許你有時候會對他的BooleanUtils.toBoolean(String)方法感興趣。
    異常-IllegalClassException, IncompleteArgumentException, NotImplementedException, NullArgumentException, UnhandledException

    ?lang.builder.*
    ??
    提供了HashCodeBuilder,EqualsBuilder, CompareToBuilder, ToStringBuilder。筆者在項目中經常用到HashCodeBuilder,具體用法參照文章前面給出的連接。
    lang.enums.* (formerly lang.enum)
    ???
    他主要的功能就是為你的常量賦值,并且給定他們的順序. For example:
    public final class ColorEnum extends Enum {
         public static final ColorEnum RED = new ColorEnum("Red");
         public static final ColorEnum GREEN = new ColorEnum("Green");
         public static final ColorEnum BLUE = new ColorEnum("Blue");
    
         private ColorEnum(String color) {
              super(color);
         }
    
         public static ColorEnum getEnum(String color) {
              return (ColorEnum) getEnum(ColorEnum.class, color);
         }
    
         public static Iterator iterator() {
              return iterator(ColorEnum.class);
         }
    }
    

    ?

    posted @ 2006-05-26 12:48 binge 閱讀(475) | 評論 (0)編輯 收藏

    Commons BeanUtils

    BeanUtils簡介

    這個組件的全稱是Bean Introspection Utilites。是屬于Jakarta Commons項目組的。主要是幫助構建javabean的屬性操作的(getter,setter),已經提供一種動態定義和訪問bean的屬性。
    接口摘要
    Converter ?通用數據類型轉換器,可以被注冊、使用用來管理對象類型的轉換
    DynaBean ?一個java對象,這個對象的屬性的名稱,數據類型和值都能被動態改變
    DynaClass ?java.lang.class的一個模擬,用來給其它類實現DynaBean接口(類似java.lang.Object和java.lang.Class的關系)
    MutableDynaClass ?一個DynaClass的專門的擴展,允許屬性動態的增加和減少。

    類摘要
    BasicDynaBean ?
    ??? DynaBean接口的最小實現
    BasicDynaClass?
    ??? ?DynaClass接口的最小實現
    BeanUtils?
    ??? 工具方法,通過反射組裝(populating)javabens的屬性。
    BeanUtilsBean?
    ??? JavaBean屬性的總體方法
    ConstructorUtils?
    ?? 提供反射工具方法,用于構造函數, MethodUtils與此相仿
    ContextClassLoaderLocal?
    ??
    ?A value that is provided per (thread) context classloader. 一個值,被提供了per (thread) context classloader.
    ConvertingWrapDynaBean?
    ?? DynaBean的一個實現,包裝了標準的JavaBean實例,因此DynaBean APIs可以訪問他的屬性,盡管這些實現允許在屬性設值的時候發生類型轉換
    ConvertUtils?
    工具方法類,用于轉換String類型變量的值到特定的類型變量的值,String類型的數組到特定類型的數組。
    ConvertUtilsBean??
    同上
    DynaProperty?
    METADATA,描述了一個DynaBean的一個屬性
    JDBCDynaClass?
    提供常用的邏輯,用于JDBC實現 DynaClass
    LazyDynaBean?
    一種DynaBean,能夠自動添加屬性到DynaClass,而且提供 Lazy List和Lazy Map的性質
    LazyDynaClass?
    一種DynaClass,實現了MutableDynaClass接口
    LazyDynaMap?
    Provides a light weight DynaBean facade to a Map with lazy map/list processing.
    為Map提供了輕量級的DynaBean facade
    ?MappedPropertyDescriptor??
    一個MappedPropertyDescriptor描述了一個map化的屬性
    MethodUtils??
    工具映射方法類,應用于一般方法而不是特定屬性。
    ?MethodUtils.MethodDescriptor? Represents the key to looking up a Method by reflection. 代表了通過反射查找方法的KEY
    ?
    PropertyUtils??
    工具方法,用于利用Java Reflection APIs來幫助一般屬性getter and setter的操作在Java對象上。
    ?PropertyUtilsBean?? 同上
    ?
    ResultSetDynaClass??
    DynaClass的實現,用于 DynaBeans,DynaBeans包裝了java.sql.ResultSet的java.sql.Row對象
    ?
    ResultSetIterator??
    java.util.Iterator的實現,用ResultSetDynaClass .的iterator()方法得到。
    ?
    RowSetDynaClass??
    DynaClass 的實現,創建了一個 包含DynaBean的in-memory容器,代表了SQL查詢的結果。
    ?
    WrapDynaBean??
    DynaBean的實現,他包裝了一個標準的JavaBean實例,因此DynaBean APIs可以被用來訪問它的屬性
    ?
    WrapDynaClass??
    DynaClass的實現,用于包裝了標準的 JavaBean實例的DynaBeans
    ?

    異常摘要

    BeanAccessLanguageException
    ??? 用于指出Bean Access Language 不能再給出的bean上執行查詢

    ConversionException
    ????
    用于指出對Converter.convert()的調用沒有成功

    NestedNullException
    ??
    用于指出Bean Access Language 不能再給出的bean上執行查詢的原因是因為嵌套的bean引用為空

    ?

    概要:?

    背景:

    JavaBeans 符合java api命名規范,它是它是java語言的組成體系之一。按照JavaBeans 設計模式可以帶來許多便利。

    JavaBeans Specification描述了完整的一套特點用來把任意一個類變成JavaBeans ,你最好讀讀這個文檔,一些最基本的在此列出:

    • ?? 類必須聲明為public,提供一個不帶參數的public構造函數。這樣可以讓其他工具或者應用程序動態的創建這個類的實例,而不需要事先知道被使用的類的名字。比如:
      String className = ...;
      ??????? Class beanClass = Class.forName(className);
      ??????? Object beanInstance = beanClass.newInstance();
    • 作為不帶參數構造函數的一個結果,類的初始化和bean的行為的配置必須完全分離。典型的做法是定義一套properties,用來修改它的行為和和這個bean代表的數據。屬性取名習慣做法是,以小寫字母開頭,由java合法字符組成。
    • 典型的,每一個property都有一個public的getter和setter方法來分別設置和取回屬性的值 ,JavaBeans Specification 定義了這個規范。用get或者set作為前綴,并把屬性的第一個字母大寫緊跟其后。比如:
      public class Employee {
      ??????????? public Employee();?? // Zero-arguments constructor
      ??????????? public String getFirstName();
      ??????????? public void setFirstName(String firstName);
      ??????????? public String getLastName();
      ??????????? public void setLastName(String lastName);
      ??????????? public Date getHireDate();
      ??????????? public void setHireDate(Date hireDate);
      ??????????? public boolean isManager();
      ??????????? public void setManager(boolean manager);
      ??????????? public String getFullName();
      ??????? }
    • 上面的例子,有個boolean值。boolean類型的屬性是以is為前綴的,這樣更容易理解。
    • 如果你既有getter又有setter,注意getter的返回值類型和setter的形參類型。另外,對同一個名字定義一個以上的類型不同的setter方法是和java規范不符的。
    • 并不是每個屬性都需要get和set方法。由上面的例子我們就可以印證這一點。
    • 創建一些get和set方法不符合上面的規范也是有可能的。具體的您可以參照完整的java規范。
    • JavaBeans Specification 還定義了其他的一些規范。

    用標準的java編碼技術,在你事先知道調用的類,事先知道要關注的屬性的情況下處理javabeans 是十分方便的。

    外部支持:

    commons-beanutils 需要一下一些包來運行:

    Standard JavaBeans

    背景:

    如上所述,標準的寫法可以給你的使用帶來方便。但是當你事先并不知道哪個類會被調用或者哪個屬性需要修改的時候怎么辦呢?java提供了一些類(比如java.beans.Introspector,他能夠在運行時檢查類而且標志出屬性的getter和setter方法),加上Reflection 機制來動態調用方法。但是,這些方法很難使用,而且暴露了過多的程序使用者不需要了解的基本結構的細節,BeanUtils的APIs企圖簡化動態setter和getter的方法。

    PropertyUtils很好的滿足我們的需求,這一章我們將深入介紹。

    首先,這里來介紹一些深入的定義:

    javabean提供的屬性可以分成三類,一些被標準的JavaBeans規范所支持,而一些只被BeanUtils所支持

    • 簡單類型(simple),最基本的屬性類型包括java最原始的數據類型(整形,字符串形),或者稍微復雜一點的對象。
    • 索引類型(index),一個索引類型的屬性存儲了一個有序的對象(相同類型)容器,可以通過整型,非負索引值單獨訪問。或者,你可以干脆用一個數組來整體訪問這個屬性。作為JavaBeans specification擴展,BeanUtils包認為java.util.list類型的屬性也可以這樣來訪問。
    • mapped,作為JavaBeans specification擴展,BeanUtils包認為java.util.map類型的屬性是map化,你可以設置和取回這個屬性通過String-valued鍵(key).

    PropertyUtils 類中提共了get和set以上各種屬性類型的多種多樣的方法。在下面的代碼片斷中,假設這個類有兩個實例。

    ?public class Employee {
    ??????? public Address getAddress(String type);
    ??????? public void setAddress(String type, Address address);
    ??????? public Employee getSubordinate(int index);
    ??????? public void setSubordinate(int index, Employee subordinate);
    ??????? public String getFirstName();
    ??????? public void setFirstName(String firstName);
    ??????? public String getLastName();
    ??????? public void setLastName(String lastName);
    ??? }
    Basic Property Access(基本屬性訪問方式)

    利用如下apis:

    • PropertyUtils.getSimpleProperty(Object bean, String name)
    • PropertyUtils.setSimpleProperty(Object bean, String name, Object value)

    利用這些方法,你可以動態操作這個對象,

    Employee employee = ...;
    ??? String firstName = (String)
    ????? PropertyUtils.getSimpleProperty(employee, "firstName");
    ??? String lastName = (String)
    ????? PropertyUtils.getSimpleProperty(employee, "lastName");
    ??? ... manipulate the values ...
    ??? PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
    ??? PropertyUtils.setSimpleProperty(employee, "lastName", lastName);
    For indexed properties, you have two choices,你有兩種選擇,可以參照下面的例子,要用到的APIS如下:

    • PropertyUtils.getIndexedProperty(Object bean, String name)
    • PropertyUtils.getIndexedProperty(Object bean, String name, int index)
    • PropertyUtils.setIndexedProperty(Object bean, String name, Object value)
    • PropertyUtils.setIndexedProperty(Object bean, String name, int index, Object value)

    例子如下:

    ? Employee employee = ...;
    ??? int index = ...;
    ??? String name = "subordinate[" + index + "]";
    ??? Employee subordinate = (Employee)
    ????? PropertyUtils.getIndexedProperty(employee, name);

    ??? Employee employee = ...;
    ??? int index = ...;
    ??? Employee subordinate = (Employee)
    ????? PropertyUtils.getIndexedProperty(employee, "subordinate", index);
    對于mapped屬性,也有兩種方式。先參照apis

    • PropertyUtils.getMappedProperty(Object bean, String name)
    • PropertyUtils.getMappedProperty(Object bean, String name, String key)
    • PropertyUtils.setMappedProperty(Object bean, String name, Object value)
    • PropertyUtils.setMappedProperty(Object bean, String name, String key, Object value)

    例子:

    Employee employee = ...;
    ??? Address address = ...;
    ??? PropertyUtils.setMappedProperty(employee, "address(home)", address);

    ??? Employee employee = ...;
    ??? Address address = ...;
    ??? PropertyUtils.setMappedProperty(employee, "address", "home", address);

    Nested Property Access(嵌套屬性訪問方式)

    如果你的屬性也是一個對象,你想訪問屬性對象的屬性時,該怎么訪問呢?

    或許,用標準的java技術直接訪問這個屬性,會寫成這樣:

    String city = employee.getAddress("home").getCity();

    用PropertyUtils類的如下apis:

    • PropertyUtils.getNestedProperty(Object bean, String name)
    • PropertyUtils.setNestedProperty(Object bean, String name, Object value)

    我們可以這樣啊來訪問:

    String city = (String)
    ????? PropertyUtils.getNestedProperty(employee, "address(home).city");

    為了方便,PropertyUtils提供了一般化的訪問方式,可以訪問任意嵌套,sample,indexed,mapped類型的屬性

    • PropertyUtils.getProperty(Object bean, String name)
    • PropertyUtils.setProperty(Object bean, String name, Object value)

    例子:

    Employee employee = ...;
    ??? String city = (String) PropertyUtils.getProperty(employee,
    ????? "subordinate[3].address(home).city");

    Dynamic Beans (DynaBeans)

    背景

    PropertyUtils如前所述被設計用來訪問存在的class的屬性的訪問方式,而不是以任何方式修改他們。一個不同的動態屬性訪問案例是,當你有一套合適的動態屬性,想用一個javabean來展示,但是你并不想真實的寫出一個類文件。除了不必保存和創建一個單獨的class文件,它的功能意味著你可以處理這樣一些情況,在這種情況下,你所關心的屬性值是動態決定的。(比如sql語句查詢出來的結果)。

    為了支持這種情況,BeanUtils提供了DynaBean接口。通過實現他的接口方法可以實現他。并且與DynaClass 接口相關聯。DynaClass 接口 定義了一個特定的DynaBean的組的屬性。就像java.lang.Class定義了所有的javabean實例的屬性一樣。

    據個例子:

    如果上面例子中的Employee是DynaBean的實現。那么我們可以這樣來訪問它的屬性。

    DynaBean employee = ...; // Details depend on which
    ???????????????????????????? // DynaBean implementation you use
    ??? String firstName = (String) employee.get("firstName");
    ??? Address homeAddress = (Address) employee.get("address", "home");
    ??? Object subordinate = employee.get("subordinate", 2);
    注意:PropertyUtils的屬性getter和setter方法知道如何訪問DynaBean的屬性。因此,你可以把你的應用中的所有屬性訪問方式都用PropertyUtils APIs。這樣你就可以不用事先考慮某個特定bean到底是如何實現的。

    因為?DynaBean?和 DynaClass都是接口,他們需要頻繁的,很多不同場合地被實現。下面的章節提供了一些標準的beanutils包,當然,如果不符合您的要求,您也可以自己去實現他們。

    BasicDynaBean and BasicDynaClass

    ? BasicDynaBean和BasicDynaClass提供了一套基本的動態屬性性能,可以應用在你需要動態定義屬性(是DynaProperty的實例)的時候。你需要先創建DynaClass來保存你將要用的一套屬性。

    例如:

    DynaProperty[] props = new DynaProperty[]{
    ??????? new DynaProperty("address", java.util.Map.class),
    ??????? new DynaProperty("subordinate", mypackage.Employee[].class),
    ??????? new DynaProperty("firstName", String.class),
    ??????? new DynaProperty("lastName",? String.class)
    ????? };
    ??? BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props);

    注意,dynaBeanClass得引數(在BasicDynaClass的構造函數中)可以為空。在這種情況下,dynaClass.getDynaBeanClass的值僅僅只是BasicDynaBean的類(In this case, the value of dynaClass.getDynaBeanClass will just be the Class for BasicDynaBean)。

    另外,你用DynaClass的newInstance()方法來實例化一個符合DynaClass的DynaBean實例,然后給他的屬性賦初始值。(和你實例一個普通的javabean,然后賦值,是一樣的)。

    DynaBean employee = dynaClass.newInstance();
    ??? employee.set("address", new HashMap());
    ??? employee.set("subordinate", new mypackage.Employee[0]);
    ??? employee.set("firstName", "Fred");
    ??? employee.set("lastName", "Flintstone");

    注意你可以這里的DynaBean類可以聲明為DynaBean取代了BasicDynaBean。一般的,如果你使用DynaBeans,你不會在意DynaBeans的具體的實際實現---你只是在乎它是一個DynaBeans,而且可以用DynaBeans的apis.

    ?如上面所講的,你可以傳遞一個DynaBean實例作為第一個引數給PropertyUtils訪問和設置屬性的方法,而且它會如你所愿的被解釋---DynaBean 的動態屬性可以被取回和修改。

    ResultSetDynaClass (Wraps ResultSet in DynaBeans)

    ? 一個很普通的DynaBean 的USER CASE就是用它來包裝其他原始集合,這些集合不是以JAVABEAN的形式展示的。最常見的情況就是當你請求JDBC驅動查詢SQL語句返回java.sql.ResultSet類型的記錄的時候,BeanUtils提供了標準的機制來把每一行resultset轉變為一個 DynaBean,參照下列:

    Connection conn = ...;
    ? Statement stmt = conn.createStatement();
    ? ResultSet rs = stmt.executeQuery
    ??? ("select account_id, name from customers");
    ? Iterator rows = (new ResultSetDynaClass(rs)).iterator();
    ? while (rows.hasNext()) {
    ??? DynaBean row = (DynaBean) rows.next();
    ??? System.out.println("Account number is " +
    ?????????????????????? row.get("account_id") +
    ?????????????????????? " and name is " + row.get("name"));
    ? }
    ? rs.close();
    ? stmt.close();

    RowSetDynaClass (Disconnected ResultSet as DynaBeans)

    盡管ResultSetDynaClass是一個用來展示sql查詢的很好的技術(當成DynaBean),但是最大的問題就是在MVC的結構之中,我們需要離線的取出查詢的所有數據,而ResultSetDynaClass必須保持和數據庫相連。

    RowSetDynaClass展示了解決這個問題的不同方法。當你構造這樣的實例,那些原始的數據被復制到一系列in-memory 的DynaBeans來代表這些結果。這個技術的優勢是,理所當然,你可以立即關閉ResultSet(和他相連的Statement),這些操作都可以在你處理被返回的數據之前。缺點就是,你需要為復制數據所需要的性能和內存買單,而且數據的大小還得讓堆內存可以適合。在許多情況下(特別是WEB APPS),這種折衷是有益處的。

    ? 額外的方便就是,RowSetDynaClass 被定義為java.io.Serializable的實現,因此它可以被序列化和反序列化。因此RowSetDynaClass展示了一種十分便利的方法來傳輸SQL結果到遠程Java-based 客戶端應用程序(比如APPLET).

    ?基本的RowSetDynaClass使用模式如下所示:

    Connection conn = ...;? // Acquire connection from pool
    ??? Statement stmt = conn.createStatement();
    ??? ResultSet rs = stmt.executeQuery("SELECT ...");
    ??? RowSetDynaClass rsdc = new RowSetDynaClass(rs);
    ??? rs.close();
    ??? stmt.close();
    ??? ...;??????????????????? // Return connection to pool
    ??? List rows = rsdc.getRows();
    ??? ...;?????????????????? // Process the rows as desired

    WrapDynaBean and WrapDynaClass

    ?下面的E文比較EASY,偶偷懶不翻了,

    OK, you've tried the DynaBeans APIs and they are cool -- very simple get() and set() methods provide easy access to all of the dynamically defined simple, indexed, and mapped properties of your DynaBeans. You'd like to use the DynaBean APIs to access all of your beans, but you've got a bunch of existing standard JavaBeans classes to deal with as well. This is where the WrapDynaBean (and its associated WrapDynaClass) come into play. As the name implies, a WrapDynaBean is used to "wrap" the DynaBean APIs around an existing standard JavaBean class. To use it, simply create the wrapper like this:

    MyBean bean = ...; DynaBean wrapper = new WrapDynaBean(bean); String firstName = wrapper.get("firstName");

    Note that, although appropriate WrapDynaClass instances are created internally, you never need to deal with them.

    Lazy DynaBeans(LazyDynaBean, LazyDynaMap and LazyDynaClass)

    ? 你鐘情于DynaBeans是因為有了它你不必對每個pojo來編碼成一個class文件。這樣能夠實現的原因是因為lazy--延遲加載。是以下的一些特性使得DynaBeans可以lazy:

    • ? Lazy property addition (lazy屬性添加)---lazy beans 使用 實現了MutableDynaClass 接口的DynaClass,DynaClass提供了添加和刪除屬性的能力。當set方法調用的時候,Lazy beans 利用這個特性來自動添加DynaClass中沒有的屬性
    • Lazy List/Array growth(lazy list/array 增長)---如果一個索引化的屬性沒有足夠的容量來容納要設置的屬性,那么List or Array 將會自動增長。
    • Lazy List/Array instantiation(Lazy List/Array實例化) ---如果一個索引化的屬性并不存在,那么他將會調用 DynaBean的indexed property getter/setter methods(比如 get(name, index) or set(name, index, value))返回一個List 或者一個Array實例。如果一個索引化的屬性沒有在DynaClass中被定義,那么他將會被自動添加而且生成一個默認的list實現的實例。
    • Lazy Map instantiation-------if a mapped property doesn't exist then calling the DynaBean's mapped property getter/setter methods (i.e. get(name, key) or set(name, key, value)) results in a new Map being instantiated. If the mapped property has not been defined in the DynaClass then it is automatically added and a default Map implementation instantiated.
    • Lazy Bean instantiation -------如果一個DynaClass 中的屬性被定義成DynaBean 或者普通的bean,但是這個屬性并不在DynaBean中存在,那么LazyDynaBean將會采用默認的empty constructor來實例化這個 bean

    LazyDynaBean

    標準lazy bean 的實現。默認和實現了MutableDynaClass接口的LazyDynaClass相關聯---盡管他可以和MutableDynaClass的任何實現一起使用。例子如下:

    ?DynaBean dynaBean = new LazyDynaBean();

    ??? dynaBean.set("foo", "bar");?????????????????? // simple

    ??? dynaBean.set("customer", "title", "Mr");????? // mapped
    ??? dynaBean.set("customer", "surname", "Smith"); // mapped

    ??? dynaBean.set("address", 0, addressLine1);???? // indexed
    ??? dynaBean.set("address", 1, addressLine2);???? // indexed
    ??? dynaBean.set("address", 2, addressLine3);???? // indexed

    LazyDynaMap

    light wieght (輕量級)DynaBean facade to a Map with all the usual lazy features。之所以是輕量級,是因為他沒有和一個包含所有屬性的DynaClass相關連。事實上,他親自實現了DynaClass。一個LazyDynaMap可以用來包裝一個存在的map,也可以自己去實例化一個Map實例

    例如:?

    If you need a new Map then to use....

    DynaBean dynaBean = new LazyDynaMap(); // create DynaBean dynaBean.set("foo", "bar"); // simple dynaBean.set("customer", "title", "Mr"); // mapped dynaBean.set("address", 0, addressLine1); // indexed Map myMap = dynaBean.getMap() // retrieve the Map

    or to use with an existing Map ....

    Map myMap = .... // exisitng Map DynaBean dynaBean = new LazyDynaMap(myMap); // wrap Map in DynaBean dynaBean.set("foo", "bar");

    LazyDynaClass

    繼承BasicDynaClass并實現MutableDynaClass接口。

    Either create a LazyDynaClass first... MutableDynaClass dynaClass = new LazyDynaClass(); // create DynaClass dynaClass.add("amount", java.lang.Integer.class); // add property dynaClass.add("orders", OrderBean[].class); // add indexed property dynaClass.add("orders", java.util.TreeMapp.class); // add mapped property DynaBean dynaBean = new LazyDynaBean(dynaClass); // Create DynaBean with associated DynaClass

    or create a LazyDynaBean and get the DynaClass... DynaBean dynaBean = new LazyDynaBean(); // Create LazyDynaBean MutableDynaClass dynaClass = (MutableDynaClass)dynaBean.getDynaClass(); // get DynaClass dynaClass.add("amount", java.lang.Integer.class); // add property dynaClass.add("myBeans", myPackage.MyBean[].class); // add 'array' indexed property dynaClass.add("myMap", java.util.TreeMapp.class); // add mapped property

    ?注意:

    MutableDynaClass 有一種受限(Restricted)屬性。When the DynaClass is restricted ,no properties can be added or removed from the DynaClass. Neither the LazyDynaBean or LazyDynaMap will add properties automatically if the DynaClass is restricted.

    關于Converters和Collections方面的知識本文不做翻譯。

    posted @ 2006-05-25 23:08 binge 閱讀(893) | 評論 (0)編輯 收藏

    proxool

    官方網址:
    http://proxool.sourceforge.net/


    ?Setting up Proxool in a Servlet environment(在servlet環境中使用proxool)
    ???Configuration(配置)
    ???有3種方式來配置proxool:
    ??????1. XML file。
    ??????代理到 JAXPConfigurator來處理xml文件。如果文件不是絕對路徑,將會定位到應用的根目錄。
    <servlet>
    ? <servlet-name>ServletConfigurator</servlet-name>
    ? <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
    ? <init-param>
    ??? <param-name>xmlFile</param-name>
    ??? <param-value>WEB-INF/proxool.xml</param-value>
    ? </init-param>
    ? <load-on-startup>1</load-on-startup>
    </servlet>?
    ???2. Property file。
    ?代理到PropertyConfigurator去解析。如果文件不是絕對路徑,將會定位到應用的根目錄。
    ???<servlet>
    ??<servlet-name>ServletConfigurator</servlet-name>
    ??<servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
    ??<init-param>
    ????<param-name>propertyFile</param-name>
    ????<param-value>WEB-INF/proxool.properties</param-value>
    ??</init-param>
    ??<load-on-startup>1</load-on-startup>
    </servlet>
    3. Init parameters。
    ???代理到PropertyConfigurator去解析。根據servlet的初始化參數創建一個Property對象。
    <servlet>
    ? <servlet-name>ServletConfigurator</servlet-name>
    ? <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
    ? <init-param>
    ??? <param-name>jdbc-0.proxool.alias</param-name>
    ??? <param-value>test</param-value>
    ? </init-param>
    ? <init-param>
    ??? <param-name>jdbc-0.proxool.driver-url</param-name>
    ??? <param-value>jdbc:hsqldb:.</param-value>
    ? </init-param>
    ? <init-param>
    ??? <param-name>jdbc-0.proxool.driver-class</param-name>
    ??? <param-value>org.hsqldb.jdbcDriver</param-value>
    ? </init-param>
    ? <load-on-startup>1</load-on-startup>
    </servlet>
    在刈除所有的連接池后,ServletConfigurator會自動停止。
    ?<servlet>
    ? <servlet-name>ServletConfigurator</servlet-name>
    ? <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
    ? <init-param>
    ??? <param-name>autoShutdown</param-name>
    ??? <param-value>false</param-value>
    ? </init-param>
    ? <load-on-startup>1</load-on-startup>
    </servlet>
    Installation.(安裝)
    ???如果在你的servlet環境中有多個web應用,你需要考慮如何來安裝proxool.這里有2種方案:
    ???1。在你應用的庫目錄(web-info/lib),他的理論如下:
    ???proxool將不會再web應用間共享。如果你重新裝在web應用,一個新的實例將會產生。除非你顯式關閉舊的proxool,否則他將繼續使用各種資源(本地資源和數據庫)。你可以用如下的辦法來關閉他們:用上面提到的ServletConfigurator或者調用ProxoolFacade的shutdown方法。
    ???2。在容器的公用目錄下或者classpath中,他的理論如下:
    ???你可以在多個web應用中共享proxool,這樣的話,如果你重新裝在單個的web應用,proxool依然在運行。如果你想沖起proxool,要么重起容器,要么全部應用停止并重新配置proxool.
    ----------------------
    本人在CSDN上的部分翻譯:
    http://blog.csdn.net/huabingl/archive/2006/05/11/725155.aspx

    posted @ 2006-05-24 22:19 binge 閱讀(562) | 評論 (0)編輯 收藏

    僅列出標題
    共4頁: 上一頁 1 2 3 4 
    主站蜘蛛池模板: 两个人看的www免费高清| 美丽姑娘免费观看在线观看中文版| 亚洲男人的天堂一区二区| 十八禁在线观看视频播放免费| 亚洲欧洲日产国码在线观看| 免费永久在线观看黄网站| 免费在线看黄网站| 国产精品免费久久| 亚洲电影一区二区| 成人免费无码大片A毛片抽搐色欲 成人免费无码大片a毛片 | 搡女人免费免费视频观看| 亚洲av永久综合在线观看尤物| 免费人成网站7777视频| 精品无码人妻一区二区免费蜜桃| 中文字幕亚洲乱码熟女一区二区| 18女人腿打开无遮掩免费| 国产99久久亚洲综合精品| 久久精品国产亚洲AV大全| 免费国产高清视频| 91九色精品国产免费| 国产伦精品一区二区免费| 亚洲色在线无码国产精品不卡| 亚洲国产另类久久久精品小说 | 一级毛片在线观看免费| 曰批全过程免费视频免费看| 亚洲AV无码乱码麻豆精品国产| 亚洲熟妇中文字幕五十中出| 中文字幕版免费电影网站| 亚洲欧美国产欧美色欲| 99人中文字幕亚洲区| 亚洲色欲一区二区三区在线观看| 日本无吗免费一二区| 思思久久99热免费精品6| 久久亚洲精品国产亚洲老地址| 亚洲一区二区三区夜色 | 狠狠色伊人亚洲综合网站色| 亚洲一区二区三区四区在线观看| 亚洲日韩中文字幕在线播放| 免费a级毛片无码a∨性按摩| 免费看片免费播放| 最新欧洲大片免费在线 |