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

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

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

    [收藏]XDoclet 說(shuō)明

    Posted on 2006-03-19 14:57 ikingqu 閱讀(683) 評(píng)論(2)  編輯  收藏 所屬分類: Others
    XDoclet是一個(gè)擴(kuò)展的Javadoc Doclet引擎。它是一種通用的java工具,可以讓你創(chuàng)建自己的javadoc @tags進(jìn)而利用XDoclet中的Templet enging基于這些@tags生成源代碼或其他文件(例如xml的deployment descriptors)。XDoclet已經(jīng)支持一些常見的任務(wù)了,例如生成web.xml和ejb-jar.xml等,用戶可以創(chuàng)建其他templets和@tags,以增加對(duì)其他技術(shù)的支持

    更宏偉的目標(biāo),是讓你可以在基于組件的開發(fā)工程中可以實(shí)現(xiàn)“持續(xù)集成”(Continuous Integration)。要點(diǎn)是在你編寫每一個(gè)組件代碼的同時(shí),指定它們的“原數(shù)據(jù)”(meta-data),也就是設(shè)定每個(gè)組件的配布屬性(deployment meta-data)。你不必?fù)?dān)心這些配布屬性會(huì)過(guò)時(shí),因?yàn)槟憧梢越佑|代碼,這些配布屬性和代碼同時(shí)被修改。這樣就做到了持續(xù)集成,整個(gè)過(guò)程很自然的就是round-trip了。我們稱之為“持續(xù)再配置”(Continuous Reconfiguation)。 XDoclet很適合成為Apache-Ant這樣的build過(guò)程的一部分。

    整個(gè)系統(tǒng)是可以擴(kuò)展的。如果需要,你可以為你的特定任務(wù)寫特別的templet(如支持新的App Server,為Toplink等定義OR Mapping schema, 甚至將servlet當(dāng)作組件來(lái)使用)。XDoclet已經(jīng)支持一些預(yù)先寫好的Templet和@tags,例如為EJB關(guān)聯(lián)的東西提供的,為自動(dòng)生成web.xml提供的等等。

    XDoclet基于以下幾個(gè)部分:


    Apache Ant Task: 和就是這種任務(wù)的例子。在你的build.xml文件中,在編譯代碼的taget之前定義。
    task的嵌套元素: 這是定義對(duì)于源代碼需要執(zhí)行的子任務(wù)的地方。例如 和。每一個(gè)子任務(wù)都可以單獨(dú)配置。
    Template文件: 子任務(wù)可以基于template文件生成輸出。template可以是包含類似于 的xml元素的文本文件。Template文件類似于JSP文件,類似于JSP tags, 實(shí)際的實(shí)現(xiàn)位于子任務(wù)類中,一個(gè)基類定義了一些共通的tag
    特別的JavaDoc @tags: 通過(guò)使用特別的JavaDoc @tags, 給每個(gè)組件定義設(shè)定。例如在SimpleServlet.java中定義一個(gè) @web:servlet name="The Simple Servlet",讓 子任務(wù)知道SimpleServlet.java包含一個(gè)servlet的定義,這樣就可以利用@web:servlet tag中的信息生成相應(yīng)的web.xml描述。
    The mege system: 為了避免過(guò)多的tags, XDoclet同時(shí)也可以使用一種merge system。例如,為了避免在EJBean源代碼中寫@jboss:table-name account,可以定義一個(gè) jaws-db-setting-Accoutn.xml文件,這個(gè)文件包含實(shí)際的XML代碼,可以被子任務(wù)合并到最終生成的jaws.xml文件中

    實(shí)際的例子,可以參見sample code和sample build.xml文件

    XDoclet是EJBDoclet的后繼者,而EJBDoclet是由Rickard Oberg -- 世界上最好的程序員之一,開放源代碼的先鋒 -- 發(fā)起的項(xiàng)目,在這個(gè)項(xiàng)目的開發(fā)過(guò)程中,逐漸發(fā)現(xiàn)不僅僅可以用于EJB,于是開始了一個(gè)新的項(xiàng)目,一開始就以一個(gè)更寬廣的應(yīng)用作為目標(biāo)。

    You can download it from http://sourceforge.net/projects/xdoclet.

    Feedback

    # re: XDoclet 說(shuō)明  回復(fù)  更多評(píng)論   

    2006-03-19 14:59 by 風(fēng)向逆轉(zhuǎn) - Java無(wú)限
    Xdoclet是什么?

    作者:zming
    轉(zhuǎn)載注明出處:http://blog.csdn.net/zmxj/archive/2005/06/17/396913.aspx

    本文的目的是讓你用最短的時(shí)間了解xdoclet技術(shù),本人并未對(duì)其作深入的研究,若理解有誤請(qǐng)指正。

    XDoclet是一個(gè)開源項(xiàng)目,可以從這里得到他:http://xdoclet.sourceforge.net/xdoclet/ 。
    XDoclet可以通過(guò)你在java源代碼中的一些特殊的注釋信息,自動(dòng)為你生成配置文件、源代碼等等,例如web、ejb的部署描述文件、為你生成struts的struts-config.xml配置文件、javascript校驗(yàn)等。
    正如《XDoclet in Action》部分章節(jié)中文版 一文中所說(shuō)的“當(dāng)初,XDoclet因?yàn)榭梢宰詣?dòng)生成EJB繁雜的接口和布署描述文件而聲名鵲起。然而,現(xiàn)在的XDoclet已經(jīng)發(fā)展成了一個(gè)全功能的、面向?qū)傩缘拇a生成框架。J2EE代碼生成只是XDoclet的一個(gè)應(yīng)用方面,它可以完成的任務(wù)已經(jīng)遠(yuǎn)遠(yuǎn)超越了J2EE和項(xiàng)目文檔的生成。”
    目前的版本可以為web、ejb、struts、webwork、hibnaate、jdo、jmx等等生成描述文件、源碼等,XDoclet提供了ant的任務(wù)target支持,完全通過(guò)ant來(lái)完成任務(wù)。

    展開XDoclet的發(fā)布包,samples目錄下有直接可以運(yùn)行的ant腳本文件。這里以web應(yīng)用target為例,說(shuō)明XDoclet能為我們作些什么。
    下面是samples中一個(gè)struts的action代碼:
    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.Action;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;

    /**
    * Simple class to test Jakarta Struts generation (Jakarta Struts 1.2 beta 2 only).
    *
    * @struts.action
    * path="/struts/foo"
    *
    * @struts.action-forward
    * name="success"
    * path="/struts/getAll.do"
    * redirect="false"
    */
    public final class StrutsAction extends Action
    {
    public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response)
    {
    return mapping.findForward("success");
    }
    }

    注意紅色的注釋部分,注意執(zhí)行完ant腳本后,將為你生成struts-config.xml中相關(guān)的配置項(xiàng),以下是腳本執(zhí)行后生成的struts-config.xml文件中的配置:

    <!-- ========== Action Mapping Definitions =================================== -->
    <action-mappings>
    <action
    path="/struts/foo"
    type="test.web.StrutsAction"
    unknown="false"
    validate="true"
    >
    <forward
    name="success"
    path="/struts/getAll.do"
    redirect="false"
    />
    </action>

    至此一點(diǎn)我們便可以了解XDoclet是如何工作的了,想想struts中的vaild配置文件、struts-config配置文件等需要我們大量的手工工作,如果再寫代碼的時(shí)候把相關(guān)的元數(shù)據(jù)信息寫在注釋里,XDoclet將為我們自動(dòng)完成這些工作,當(dāng)然像 @struts.action 、@struts.action-forward 等這些特定的注釋標(biāo)簽需要去查XDoclet的相關(guān)文檔了,像前面說(shuō)的一樣,Xdoclet對(duì)目前流行的多種框架、技術(shù)都提供了相關(guān)的支持。相信在一些情況下,Xdoclet會(huì)大大提高我們的工作效率的,了解更多信息請(qǐng)參考Xdoclet網(wǎng)站http://xdoclet.sourceforge.net/xdoclet/ 。

    # re: XDoclet 說(shuō)明  回復(fù)  更多評(píng)論   

    2006-03-19 15:00 by 風(fēng)向逆轉(zhuǎn) - Java無(wú)限
    《XDoclet in Action》部分章節(jié)中文版

    轉(zhuǎn)自:http://www.javaresearch.org/article/showarticle.jsp?column=331&thread=26106

    XDoclet起步

    XDoclet是一個(gè)代碼生成工具,它可以把你從Java開發(fā)過(guò)程中繁重的重復(fù)勞動(dòng)中解脫出來(lái)。XDoclet可以讓你的應(yīng)用系統(tǒng)開發(fā)的更加快速,而你只要付比原先更少的努力。你可以把你手頭上的冗長(zhǎng)而又必需的代碼交給它幫你完成,你可以逃脫“deployment descriptor地獄”,你還可以使你的應(yīng)用系統(tǒng)更加易于管理。而你所要做的,只不過(guò)是在你的注釋里,多加一些類javadoc屬性。然后,你會(huì)驚訝于XDoclet為了做到的一切。
    討論XDoclet,有一點(diǎn)比較容易產(chǎn)生混淆,那就是XDoclet不但是一系統(tǒng)的代碼生成應(yīng)用程序,而且它本身還是一個(gè)代碼生成框架。雖然每個(gè)應(yīng)用系統(tǒng)的細(xì)節(jié)千變?nèi)f化(比如EJB代碼生成和Struts代碼生成是不一樣的,而JMX代碼生成又是另一番景象),但這些代碼生成的核心概念和用法卻是類似的。
    在這一章里,我們將會(huì)看到滲透到所有XDoclet代碼生成程序當(dāng)中的XDoclet框架基礎(chǔ)概念。但在之前,我們先從一個(gè)例子入手。

    2.1 XDoclet in action

    每一個(gè)程序員都會(huì)認(rèn)識(shí)到,他們的程序永遠(yuǎn)也不會(huì)完成??倳?huì)有另一些的功能需要添加,另一些的BUG需要修正,或者需要不斷的進(jìn)行重構(gòu)。所以,在代碼里添加注釋,提醒自己(或者其他的程序員)有哪些任務(wù)需要完成已成為一個(gè)共識(shí)。
    如何來(lái)跟蹤這些任務(wù)是否完成了呢?理想情況下,你會(huì)收集整理出來(lái)一個(gè)TODO任務(wù)列表。在這方面,XDoclet提供了一個(gè)強(qiáng)大的TODO生成器,來(lái)幫助你完成這個(gè)任務(wù)。這是一個(gè)把XDoclet引入項(xiàng)目的好機(jī)會(huì)。
    2.1.1 一個(gè)公共的任務(wù)
    假設(shè)你正在開發(fā)一個(gè)使用了勺子的類。
    public class Matrix {
      // TODO ? 需要處理當(dāng)沒(méi)有勺子的情況
      public void reload() {
        // ...
        Spoon spoon = getSpoon();
        // ...
      }
    }
    理想情況下,你在下一次閱讀這段代碼的時(shí)候,你會(huì)處理這個(gè)“空勺子”(null spoon)的問(wèn)題。但如果你過(guò)了很久才回來(lái)看這段代碼,你還會(huì)記得在這個(gè)類里還有一些工作要做嗎?當(dāng)然,你可以在你的源碼里全局搜索TODO,甚至你的集成開發(fā)環(huán)境有一個(gè)內(nèi)建的TODO列表支持。但如果你想把任務(wù)所在的類和方法也標(biāo)注出來(lái)的話,XDoclet可以是另一種選擇。XDoclet可以為你的項(xiàng)目生成一個(gè)TODO報(bào)表。

    2.1.2 添加X(jué)Doclet標(biāo)簽
    為了把你的TODO項(xiàng)目轉(zhuǎn)換成另一種更加正式的格式,你需要對(duì)代碼進(jìn)行一些細(xì)微的改動(dòng)。如下所示:
    public class Matrix {
      /** @todo 需要處理當(dāng)沒(méi)有勺子的情況 */
      public void reload() {
        // ...
      }
    }
    這里加入了一個(gè)XDoclet需要的類javadoc標(biāo)簽。XDoclet會(huì)使用這些標(biāo)簽標(biāo)記的信息,以及在這種情況下標(biāo)簽所處的類和方法,來(lái)生成TODO報(bào)表。

    2.1.3 與Ant集成
    要生成TODO報(bào)表,你需要確保在你的機(jī)器上正確安裝了XDoclet。
    在Ant任務(wù)里,最少要包含一個(gè)目標(biāo)(例如init目標(biāo))定義<documentdoclet>任務(wù),這是一個(gè)Ant自定義任務(wù),例如:
      <taskdef name=”documentdoclet”
        classname=”xdoclet.modules.doc.DocumentDocletTask”
        classname=”xdoclet.lib.path” />
    這個(gè)<documentdoclet>任務(wù)是XDoclet核心代碼生成應(yīng)用程序中的一個(gè)。
    現(xiàn)在,你可以在Ant構(gòu)建文件中加入一個(gè)todo目標(biāo)調(diào)用這個(gè)任務(wù)來(lái)生成TODO報(bào)表,如:
      <target name=”todo” depends=”init”>
        <documentdoclet destdir=”todo”>
          <fileset dir=”${dir.src}”>
            <include name=”**/*.java” />
          </fileset>
          <info/>
        </documentdoclet>
      </target>
    <info>子任務(wù)會(huì)遍歷你的源文件,查找todo標(biāo)簽,并在todo子目錄下生成HTML格式的TODO報(bào)表。

    2.1.4 創(chuàng)建一個(gè)更加職業(yè)化的TODO報(bào)表
    XDoclet生成的TODO報(bào)表可以有一個(gè)更加職業(yè)化的外表。報(bào)表會(huì)列出一個(gè)概覽,顯示在哪個(gè)包哪個(gè)類里有todo項(xiàng)(以及todo項(xiàng)的個(gè)數(shù))。Todo項(xiàng)可以跟在方法、類和域上,從報(bào)表上可以清楚的區(qū)別它們。類級(jí)別的todo項(xiàng)會(huì)標(biāo)注class,方法級(jí)別的todo項(xiàng)會(huì)在方法簽名上標(biāo)注M。構(gòu)造函數(shù)和域相關(guān)的todo項(xiàng)也會(huì)進(jìn)行相似的標(biāo)注。
    這個(gè)任務(wù)看起來(lái)很簡(jiǎn)單,但考慮到你所需要做的只是在注釋上添加一些格式化的@todo標(biāo)簽,相對(duì)于那種只有人才可以理解的無(wú)格式的松散的注釋,這種標(biāo)簽是機(jī)器可讀的,也更容易編程處理。生成的輸出也更容易閱讀并且更加的商業(yè)化。

    2.2 任務(wù)和子任務(wù)
    生成todo報(bào)表,只是XDoclet可以完成的事情當(dāng)中的冰山一角。當(dāng)初,XDoclet因?yàn)榭梢宰詣?dòng)生成EJB繁雜的接口和布署描述文件而聲名鵲起。然而,現(xiàn)在的XDoclet已經(jīng)發(fā)展成了一個(gè)全功能的、面向?qū)傩缘拇a生成框架。J2EE代碼生成只是XDoclet的一個(gè)應(yīng)用方面,它可以完成的任務(wù)已經(jīng)遠(yuǎn)遠(yuǎn)超越了J2EE和項(xiàng)目文檔的生成。

    2.2.1 XDoclet 任務(wù)
    到現(xiàn)在為止,我們一直在討論使用XDoclet生成代碼,但事實(shí)上,更確切的說(shuō)法應(yīng)該是,我們使用XDoclet的一個(gè)特定的任務(wù)來(lái)生成代碼,比如<ejbdoclet>。每一個(gè)XDoclet任務(wù)關(guān)注于一個(gè)特定的領(lǐng)域,并提供這個(gè)領(lǐng)域的豐富的代碼生成工具。
    [定義:任務(wù)(Tasks)是XDoclet里可用的代碼生成應(yīng)用程序的高層概念。]
    在XDoclet里,目前已有如下所示的七個(gè)核心任務(wù)。
    <ejbdoclet>:面向EJB領(lǐng)域,生成EJB、工具類和布署描述符。
    <webdoclet>:面向Web開發(fā),生成serlvet、自定義標(biāo)簽庫(kù)和web框架文件。
    <hibernatedoclet>:Hibernate持續(xù),配置文件、Mbeans
    <jdodoclet>:JDO,元數(shù)據(jù),vender configuration
    <jmxdoclet>:JMX,MBean接口,mlets,配置文件。
    <doclet>:使用用戶自定義模板來(lái)生成代碼。
    <documentdoclet>:生成項(xiàng)目文件(例如todo列報(bào)表)
    這其中,<ejbdoclet>最常用,并且很多項(xiàng)目也僅僅使用XDoclet來(lái)進(jìn)行EJB代碼生成。<webdoclet>是其次一個(gè)常用的代碼生成任務(wù)。當(dāng)然,在一個(gè)項(xiàng)目中同時(shí)使用幾個(gè)XDoclet任務(wù)是可能的(并且也是推薦的),但在這些任務(wù)之間是完全獨(dú)立的,它們彼此之間并不能進(jìn)行直接的交流。

    2.2.2 XDoclet子任務(wù)
    XDoclet的任務(wù)是領(lǐng)域相關(guān)的,而在某個(gè)特定領(lǐng)域的XDoclet任務(wù),又由許許多多緊密耦合在一起的子任務(wù)組成的,這些子任務(wù)每個(gè)都僅僅執(zhí)行一個(gè)非常特定和簡(jiǎn)單的代碼生成任務(wù)。
    [定義:子任務(wù)(subtasks)是由任務(wù)提供的單目標(biāo)的代碼生成過(guò)程]
    任務(wù)提供子任務(wù)執(zhí)行時(shí)的上下文,并且把這些相關(guān)的子任務(wù)組織管理了起來(lái)。任務(wù)會(huì)依賴這些子任務(wù)來(lái)生成代碼。在一個(gè)任務(wù)當(dāng)中調(diào)用多個(gè)子任務(wù)來(lái)協(xié)同完成各種各樣比較大型的代碼生成任務(wù)是非常常見的。比如,在開發(fā)EJB時(shí),你可能想要為每一個(gè)bean生成一個(gè)home接口,一個(gè)remote接口以及ejb-jar.xml布署描述符文件。這就是在<ejbdoclet>任務(wù)的上下文環(huán)境中的三個(gè)獨(dú)立的代碼生成子任務(wù)。
    子任務(wù)可以隨意的組合排列,以滿足項(xiàng)目代碼生成的需要。某個(gè)XDoclet任務(wù)包含的子任務(wù)經(jīng)常會(huì)共享功能和在源文件中使用相同的XDoclet標(biāo)簽。這意味著當(dāng)你開始一個(gè)任務(wù)的時(shí)候,你可以很容易的集成進(jìn)一個(gè)相關(guān)的子任務(wù),而不需要很大的改動(dòng)。

    子任務(wù)交互
    讓我們以<ejbdoclet>任務(wù)為例,看一下相關(guān)的子任務(wù)之間是如何進(jìn)行關(guān)聯(lián)的。假設(shè)你正在開發(fā)一個(gè)CMP(容器管理持久化)實(shí)體Bean。你想要使用一些<ejbdoclet>的子任務(wù):
    ?<deploymentdescriptor>:生成ejb-jar.xml布署描述符文件。
    ?<localhomeinterface>:生成local home接口。
    ?<localinterface>:生成local接口。
    在執(zhí)行如上子任務(wù)的時(shí)候,你需要標(biāo)記出你的實(shí)體Bean的CMP域。當(dāng)你發(fā)布你的bean的時(shí)候,你還需要在開發(fā)商相關(guān)的布署描述符中提供某個(gè)特定的關(guān)系數(shù)據(jù)庫(kù)中的特定表和列與你的CMP實(shí)體Bean的映射關(guān)系。XDoclet可以讓你在原先已存在的CMP XDoclet屬性基礎(chǔ)上再加上一些關(guān)系映射屬性,然后,你就可以在任務(wù)中加入一個(gè)開發(fā)商相關(guān)的子任務(wù)(例如<jboss>或者<weblogic>)來(lái)生成布署描述符文件。XDoclet提供了幾乎所有的應(yīng)用服務(wù)器的支持,你只需要一些初始化的小改動(dòng),就可以進(jìn)行這些應(yīng)用服務(wù)器相關(guān)的代碼生成了。
    但那只是冰山一角。你還可以使用<entitycmp>子任務(wù)為為你的bean生成一個(gè)實(shí)體bean接口的實(shí)現(xiàn)子類。如果你使用<valueobject>子任務(wù)來(lái)為了你的bean生成值對(duì)象,<entityemp>子任務(wù)還會(huì)為你的值對(duì)象生成方法的實(shí)現(xiàn)代碼。
    覺(jué)得不可思議了吧??上Doclet沒(méi)有提供<cupofcoffee>子任務(wù),要不然我們可以喝杯咖啡,休息一下啦。
    這里不是想向你介紹<ejbdoclet>所有的子任務(wù)或者<ejbdoclet>可以完成的所有代碼生成功能,而僅僅是想向你展示一下任務(wù)的子任務(wù)之間是如何工作在一起的。一旦你開始并熟悉了一個(gè)XDoclet 子任務(wù),熟悉另一個(gè)子任務(wù)會(huì)變得非常簡(jiǎn)單- 那種每個(gè)子任務(wù)都是孤立的相比,使用這種可以相互協(xié)作的子任務(wù),開發(fā)成本會(huì)顯著的降低,效果也更加的立竿見影。

    2.3 使用Ant執(zhí)行任務(wù)
    XDoclet“嫁”給了Ant。XDoclet任務(wù)就是Ant的自定義任務(wù),除此以外,沒(méi)有其他運(yùn)行XDoclet任務(wù)的方法。所幸的是,Ant已經(jīng)成為了Java構(gòu)建工具事實(shí)上的標(biāo)準(zhǔn),所以這不算什么限制。事實(shí)上,反過(guò)來(lái),XDoclet與Ant的這種“親密”關(guān)系使得XDoclet可以參與到任何Ant構(gòu)建過(guò)程當(dāng)中去。
    2.3.1 聲明任務(wù)
    XDoclet并沒(méi)有和Ant一起發(fā)布,所以如果你想要使用XDoclet的話,就需要單獨(dú)的下載和安裝。在使用任何一個(gè)XDoclet的任務(wù)之前,你首先需要在使用Ant的<taskdef>任務(wù)來(lái)聲明它。例如:
    <taskdef name=”ejbdoclet”
      classname=”xdoclet.modules.ejb.EjbDocletTask”
      classpathref=”xdoclet.lib.path”/>
    如果你熟悉Ant的話,你就會(huì)知道這段代碼是告訴Ant加載<ejbdoclet>的任務(wù)定義。當(dāng)然,你也可以以你喜歡的任何方式來(lái)命名這個(gè)自定義任務(wù),但最好還是遵守標(biāo)準(zhǔn)的命名規(guī)律以免發(fā)生混淆。classname和classpathref屬性告訴Ant到哪里去找實(shí)現(xiàn)這個(gè)自定義任務(wù)的XDoclet類。如果你想使用其他的XDoclet任務(wù),就必須要類似這樣首先聲明這個(gè)任務(wù)。
    一般共通的做法是,把所有需要使用的XDoclet任務(wù)都放在Ant的一個(gè)目標(biāo)里聲明,這樣在其他的目標(biāo)里如果需要使用這些任務(wù),只要depends這個(gè)任務(wù)就可以了。你可能已經(jīng)在Ant的構(gòu)建文件里包含了init目標(biāo),這就是放置XDoclet任務(wù)聲明的好地方(當(dāng)然如果你沒(méi)有,你也可以建一個(gè))。下面的例子就是在一個(gè)init目標(biāo)里加入了<ejbdoclet>和<webdoclet>的聲明:
    <target name=”init”>
      <taskdef name=”documentdoclet”
        classname=”xdoclet.modules.doc.DocumentDocletTask”
        classpathref=”xdoclet.lib.path” />
        <taskdef name=”ejbdoclet”
          classname=”xdoclet.modules.ejb.EjbDocletTask”
          classpathref=”xdoclet.lib.path” />
        <taskdef name=”webdoclet”
          classname=”xdoclet.modules.web.WebDocletTask”
          classpathref=”xdoclet.lib.path” />
    </target>
    現(xiàn)在,任務(wù)聲明好了,XDoclet“整裝待發(fā)”。

    2.3.2 使用任務(wù)
    你可以在任何目標(biāo)里使用聲明好的任務(wù)。在任務(wù)的上下文環(huán)境里,可以調(diào)動(dòng)相關(guān)的子任務(wù)。讓我們看一個(gè)例子,這個(gè)例子調(diào)用了<ejbdoclet>任務(wù)。不要擔(dān)心看不懂語(yǔ)法的細(xì)節(jié),現(xiàn)在你只需要關(guān)心一些基礎(chǔ)概念就可以了。
    <target name=”generateEjb” depends=”init”>
      <ejbdoclet destdir=”${gen.src.dir}”>
        <fileset dir=”${src.dir}”>
          <include name=”**/*Bean.java”/>
        </fileset>
      <deploymentdescriptor destdir=”${ejb.deployment.dir}”/>
      <homeinterface/>
      <remoteinterface/>
      <localinterface/>
       <localhomeinterface/>
      </ejbdoclet>
    </target>
    把任務(wù)想像成一個(gè)子程序運(yùn)行時(shí)需要的一個(gè)配置環(huán)境(記住,子任務(wù)才是真正進(jìn)行代碼生成工作的)。當(dāng)調(diào)用一個(gè)子任務(wù)時(shí),子任務(wù)從任務(wù)繼承上下文環(huán)境,當(dāng)然,你也可以根據(jù)需要隨意的覆蓋這些值。在上面的例子里,因?yàn)?lt;deploymentdescriptor>子任務(wù)生成的布署描述符文件和其他生成各種接口的子任務(wù)生成的Java源文件需要放在不同的位置,所以覆蓋了destdir的屬性值。布署描述符文件需要放在一個(gè)在打包EJB JAR文件的時(shí)候可以容易包含進(jìn)來(lái)的地方,而生成的Java代碼則需要放置在一個(gè)可以調(diào)用Java編譯器進(jìn)行編譯的地方。需要這些子任務(wù)之間是緊密關(guān)聯(lián)的,但只要你需要,你可以有足夠的自主權(quán)控制任務(wù)的生成環(huán)境。
    <fileset>屬性同樣被應(yīng)用到所有的子任務(wù)。這是一個(gè)Ant的復(fù)雜類型(相對(duì)于文本和數(shù)值的簡(jiǎn)單類型),所以以子元素的方式在任務(wù)中聲明。不要把它和子任務(wù)混為一談。當(dāng)然,如果你想在某個(gè)子任務(wù)中另外指定一個(gè)不同的輸入文件集,你也可以在這個(gè)子任務(wù)中放置一個(gè)<fileset>子元素來(lái)覆蓋它。
    子任務(wù)的可配置選項(xiàng)遠(yuǎn)遠(yuǎn)不止這些。我們會(huì)在下一章繼續(xù)介紹所有的任務(wù)和子任務(wù),以及常用的配置選項(xiàng)。

    2.4 用屬性標(biāo)注你的代碼
    可重用的代碼生成系統(tǒng)需要輸入來(lái)生成感興趣的輸出。一個(gè)解析器生成器也需要一個(gè)語(yǔ)言描述來(lái)解析生成解析器。一個(gè)商務(wù)對(duì)象代碼生成器需要領(lǐng)域模型來(lái)知道要生成哪些商務(wù)對(duì)象。XDoclet則需要Java源文件做為輸出來(lái)生成相關(guān)的類或者布署/配置文件。
    然而,源文件可能并沒(méi)有提供代碼生成所需要的所有信息??紤]一個(gè)基于servlet的應(yīng)用,當(dāng)你想生成web.xml文件的時(shí)候,servlet源文件僅可以提供類名和適當(dāng)?shù)膕ervlet接口方法。其他的信息比如URI pattern映射、servlet需要的初始化參數(shù)等信息并沒(méi)有涵蓋。顯而易見,如果class并沒(méi)有提供這些信息給你,你就需要自己手動(dòng)在web.xml文件時(shí)填寫這些信息。
    XDoclet當(dāng)然也不會(huì)知道這些信息。幸運(yùn)的是,解決方法很簡(jiǎn)單。如果所需信息在源文件時(shí)沒(méi)有提供,那就提供它,做法就是在源文件里加入一些XDoclet屬性。XDoclet解析源文件,提取這些屬性,并把它們傳遞給模板,模板使用這些信息生成代碼。

    2.4.1 剖析屬性
    XDoclet屬性其實(shí)就是javadoc的擴(kuò)展。它們?cè)谕獗砩虾褪褂蒙隙加衘avadoc屬性一樣,可以放置在javadoc文檔注釋里。文檔注釋以/**開始,*/結(jié)尾。下面是一個(gè)簡(jiǎn)單的例子:
    /**
    * 這是一段javadoc注釋。
    * 注釋可以被分解成多行,每一行都以星號(hào)開始。
    */
    在注釋里的所有文本都被視為javadoc注釋,并且都能夠被XDoclet訪問(wèn)到。注釋塊一般都與Java源文件中的某個(gè)實(shí)體有關(guān),并緊跟在這個(gè)實(shí)體的前面。沒(méi)有緊跟實(shí)體的注釋塊將不會(huì)被處理。類(或者接口)可以有注釋塊,方法和域也可以有自己的注釋塊,比如:
    /**
    * 類注釋塊
    */
    public class SomeClass {
      /** 域注釋塊 */
      private int id;
      /**
    * 構(gòu)造函數(shù)注釋塊
    */
      public SomeClass() {
        // ...
      }
      /**
       * 方法注釋塊
       */
      public int getId() {
        return id;
      }
    }
    注釋塊分成兩部分:描述部分和標(biāo)簽部分。當(dāng)遇到第一個(gè)javadoc標(biāo)簽時(shí),標(biāo)簽部分開始。Javadoc標(biāo)簽也分成兩部分:標(biāo)簽名和標(biāo)簽描述。標(biāo)簽描述是可選的,并且可以多行。例如:
    /**
    * 這是描述部分
    * @tag1 標(biāo)簽部分從這里開始
    * @tag2
    * @tag3 前面一個(gè)標(biāo)簽沒(méi)有標(biāo)簽描述。
    * 這個(gè)標(biāo)簽有多行標(biāo)簽描述。
    */
    XDoclet使用參數(shù)化標(biāo)簽擴(kuò)展了javadoc標(biāo)簽。在XDoclet里,你可以在javadoc標(biāo)簽的標(biāo)簽描述部分加入name=”value”參數(shù)。這個(gè)微小的改動(dòng)大大增強(qiáng)了javadoc標(biāo)簽的表達(dá)能力,使得javadoc標(biāo)簽可以用來(lái)描述復(fù)雜的元數(shù)據(jù)。下面的代碼顯示了使用XDoclet屬性描述實(shí)體Bean方法:
    /**
    * @ejb.interface-method
    * @ejb.relation
    * name=”blog-entries”
    * role-name=”blog-has-entries”
    * @ejb.value-object
    * compose=”com.xdocletbook.blog.value.EntryValue”
    * compose-name=”Entry”
    * members=”com.xdocletbook.blog.interfaces.EntryLocal”
    * members-name=”Entries”
    * relation=”external”
    * type=”java.util.Set”
    */
    public abstract Set getEntries();
    參數(shù)化標(biāo)簽允許組合邏輯上相關(guān)聯(lián)的屬性。你可以加入描述這個(gè)類的元信息,使得這個(gè)類的信息足夠生成代碼。另外,程序員借由閱讀這樣的元信息,可以很快的理解這個(gè)類是如何使用的。(如果這個(gè)例子上的元信息你看不懂,不要擔(dān)心,在第4章里,我們會(huì)學(xué)到EJB相關(guān)的標(biāo)簽以及它們的涵意。)
    另外,請(qǐng)注意上面的例子中,所有的標(biāo)簽名都以ejb開頭。XDoclet使用namespace.tagname的方式給標(biāo)簽提供了一個(gè)命名空間。這樣做除了可以跟javadoc區(qū)別開來(lái)以外,還可以把任務(wù)相關(guān)的標(biāo)簽組織起來(lái),以免任務(wù)之間的標(biāo)簽產(chǎn)生混淆。

    2.5 代碼生成模式
    XDoclet是一種基于模板的代碼生成引擎。從高層視圖上來(lái)看,輸出文件其實(shí)就是由解析執(zhí)行各式各樣的模板生成出來(lái)的。如果你理解了模板以及它所執(zhí)行的上下文環(huán)境,就可以確切的認(rèn)識(shí)到,XDoclet可以生成什么,不可以生成什么。如果你正在評(píng)估XDoclet平臺(tái),理解這些概念是非常重要的。要不然,你可能會(huì)錯(cuò)過(guò)XDoclet的許多強(qiáng)大的功能,也可能會(huì)被XDoclet的一些限制感到迷惑。
    XDoclet運(yùn)行在在Ant構(gòu)建文件環(huán)境中,它提供了Ant自定義任務(wù)和子任務(wù)來(lái)與XDoclet引擎交互。任務(wù)是子任務(wù)的容器,子任務(wù)負(fù)責(zé)執(zhí)行代碼生成。子任務(wù)調(diào)用模板。模板提供了你將生成代碼的餅干模子。XDoclet解析輸入的源文件,提取出源文件中的XDoclet屬性元數(shù)據(jù),再把這些數(shù)據(jù)提供給模板,驅(qū)動(dòng)模板執(zhí)行。除此之外,模板還可以提供合并點(diǎn)(merge points),允許用戶插入一些模板片斷(合并文件merge files)來(lái)根據(jù)需要定制代碼生成。
    2.5.1 模板基礎(chǔ)
    XDoclet使用代碼模板來(lái)生成代碼。模板(template)是你想生成文件的原型。模板里使用一些XML標(biāo)簽來(lái)指導(dǎo)模板引擎如何根據(jù)輸入類以及它們的元數(shù)據(jù)來(lái)調(diào)整代碼的生成。
    [定義:模板(template)是生成代碼或描述文件的抽象模視圖。當(dāng)模板被解析的時(shí)候,指定的細(xì)節(jié)信息會(huì)被填入。]
    模板一般情況下會(huì)有一個(gè)執(zhí)行環(huán)境。模板可能應(yīng)用在一個(gè)類環(huán)境(轉(zhuǎn)換生成transform generation),也有可能應(yīng)用在一個(gè)全局環(huán)境(聚集生成aggregate generation)。轉(zhuǎn)換生成和聚集生成是XDoclet的兩種類型的任務(wù)模式,理解它們之間的區(qū)別對(duì)于理解XDoclet是非常重要的。
    當(dāng)你使用XDoclet生成布置描述符文件時(shí),你使用的是聚集生成。布置描述符文件并不僅僅只與一個(gè)類相關(guān),相反,它需要從多個(gè)類里聚集信息到一個(gè)輸入文件。在這種生成模式里,解析一次模板只會(huì)生成一個(gè)輸出文件,不管有多少個(gè)輸入文件。
    在轉(zhuǎn)換生成模式里,模板遇到每一個(gè)源文件就會(huì)解析一次,根據(jù)該文件類的上下文環(huán)境生成輸出。這種生成模式會(huì)為每一個(gè)輸入文件生成一個(gè)輸出文件。
    轉(zhuǎn)換生成模式的一個(gè)很好的例子是生成EJB的local和remote接口。顯然,接口是和Bean類一一相關(guān)的。從每一個(gè)類里提取信息(類以及它的方法、域、接口以及XDoclet屬性等信息)轉(zhuǎn)換出接口。除此以外,不需要其他的信息。
    從實(shí)現(xiàn)里提取出接口似乎有點(diǎn)反向。如果你手寫程序的話,一般來(lái)說(shuō)會(huì)先定義一個(gè)接口,然后再寫一個(gè)類來(lái)關(guān)現(xiàn)它。但XDoclet做不到,XDoclet不可能幫你實(shí)現(xiàn)一個(gè)已有接口,因?yàn)樗豢赡軒湍闵赡愕臉I(yè)務(wù)邏輯。當(dāng)然,如果業(yè)務(wù)邏輯可以從接口本身得到(比如JavaBean的get/set訪問(wèn)器)或者使用XDoclet屬性聲明好,那么生成業(yè)務(wù)邏輯代碼來(lái)實(shí)現(xiàn)一個(gè)接口也不是不可能。但一般情況下,這樣做不太現(xiàn)實(shí)。相比而言,提供一個(gè)實(shí)現(xiàn),并描述接口與這個(gè)實(shí)現(xiàn)之間的關(guān)聯(lián)就容易多了。
    聚集生成和轉(zhuǎn)換生成主要區(qū)別在它們的環(huán)境信息上。即使一個(gè)代碼生成任務(wù)中生成一個(gè)Java文件,一般也不常用聚集生成,因?yàn)樯梢粋€(gè)Java類還需要一些重要信息如類所處的包以及你想生成的類名,在這種環(huán)境下是無(wú)法提供的。如果一定要使用聚集生成的話,那就需要在另一個(gè)單獨(dú)的地方提供好配置信息了。
    2.5.2 模板標(biāo)簽
    在還沒(méi)見到模板長(zhǎng)啥樣子之前,我們已經(jīng)比較深入的認(rèn)識(shí)它了。那模板文件究竟長(zhǎng)啥樣子呢?它有點(diǎn)像JSP文件。它們都包含文件和XML標(biāo)簽,生成輸出文件時(shí)XML標(biāo)簽會(huì)被解析,然后生成文本并顯示在XML標(biāo)簽所處的位置上。除了以XDt為命名空間打頭的XML標(biāo)簽會(huì)被XDoclet引擎解析以外,其余的XML標(biāo)簽XDoclet會(huì)忽略不管。下面的代碼片斷顯示了XDoclet模板的“經(jīng)典造型”:
      public class
        <XDtClass:classOf><XDtEjbFacade:remoteFacadeClass/></XDtClass:classOf>
        Extends Observabe {
        static <XDtClass:classOf><XDtEjbFacade:remoteFacadeClass/></XDtClass:classOf>
          _instance = null;
        public static <XDtClass:classOf><XDtEjbFacade:remoteFacadeClass/></XDtClassOf>
          getInstance() {
          if (_instance == null) {
            _instance =
    new <XDtClass:classOf><XDtEjbFacade:remoteFacadeClass/>
              </XDtClass:classOf>();
         ?。?
          return _instance;
    }
    }
    研究一下這個(gè)模板,你會(huì)發(fā)現(xiàn),它生成的是一個(gè)類定義。這個(gè)類里定義了一個(gè)靜態(tài)變量instance,并且使用一個(gè)靜態(tài)方法來(lái)控制這個(gè)靜態(tài)文件的訪問(wèn)。借助Java語(yǔ)法,你可以很容易的推斷出那些XDoclet模板標(biāo)簽的目錄是生成類名,雖然對(duì)于這個(gè)標(biāo)簽如何工作你還并不是很了解。
    即使你從沒(méi)打算過(guò)要自己寫模板,但理解模板是如何被解析運(yùn)行的還是很有必要的。遲早你會(huì)調(diào)用到一個(gè)運(yùn)行失敗的XDoclet任務(wù),沒(méi)有產(chǎn)生你所期望的輸出,那么最快捷的找出原因的方法就是直接檢查模板文件,看看是哪里出了問(wèn)題。
    讓我們看一下生成靜態(tài)域定義的片斷:
    static <XDtClass:classOf><XDtEjbFacade:remoteFacadeClass/></XDtClass:classOf>
        _instance = null;
    在XDoclet的眼里,這段模板代碼很簡(jiǎn)單,那就是:
      static <tag/> _instance = null;
    XDoclet解析執(zhí)行標(biāo)簽,如果有輸出的話,把輸入置回到文本里去。有些標(biāo)簽會(huì)執(zhí)行一些運(yùn)算,把輸出放回到一個(gè)流里。這樣的標(biāo)簽稱之為內(nèi)容標(biāo)簽(content tags),因?yàn)樗鼈儺a(chǎn)生內(nèi)容。
    另一種類型的標(biāo)簽稱之為BODY標(biāo)簽。BODY標(biāo)簽在開始和結(jié)束標(biāo)簽之間存在文本。而BODY標(biāo)簽強(qiáng)大就強(qiáng)大在這些文本自己也可以是一斷可以由外圍標(biāo)簽解析的模板片斷。比如在上面的例子里,XDtClass:classOf標(biāo)簽,它們的內(nèi)容就是模板片斷:
      <XDtEjbFacade:remoteFacadeClass/>
    classOf標(biāo)簽解析這段模板,提取出全限制的內(nèi)容,然后剃除前面的包面,只輸出類名。BODY標(biāo)簽并不總是會(huì)解析它的內(nèi)容,在做這件事之前,它們會(huì)事先檢查一些外部判斷條件(比如檢查檢查你正在生成的是一個(gè)接口還是一個(gè)類)。這里標(biāo)標(biāo)簽稱之為條件標(biāo)簽(conditional tags)。還有一些BODY標(biāo)簽提供類似迭代的功能,它的內(nèi)容會(huì)被解析多次。比如一個(gè)標(biāo)簽針對(duì)類里的每一個(gè)方法解析一次內(nèi)容。
    XDoclet標(biāo)簽提供了許多高層次的代碼生成功能,但是有時(shí)候,它們可能顯得不夠靈活,或者表達(dá)能力滿足不了你的需要。這時(shí)候,相對(duì)于另外開發(fā)一套通用功能的模板引擎相比,你可以選擇擴(kuò)展XDoclet模板引擎。你可以使用更具表述能力、功能更加強(qiáng)大的Java平臺(tái)開發(fā)你自己的一套標(biāo)簽。

    2.6 使用合并定制
    代碼生成系統(tǒng)之所以使用的不多,主要原因就在于它們往往只能生成一些死板的、不夠靈活的代碼。大多數(shù)代碼生成系統(tǒng)不允許你改動(dòng)它們生成的代碼;如果,如果這個(gè)系統(tǒng)不夠靈活,你所能做到的最好的擴(kuò)展就是應(yīng)用繼承擴(kuò)展生成的代碼,或者使用一些共通的設(shè)計(jì)模式(比如Proxy和Adaptor)來(lái)滿足你的需要。無(wú)論如此,這都不是產(chǎn)生你想生成的代碼的好辦法。代碼生成器最好能做到所生成即所得WYGIWYG(what you generate is what you get),來(lái)取代你需要花費(fèi)大量的時(shí)間來(lái)粉飾生成出來(lái)的并不滿足要求的代碼。所以,對(duì)于代碼生成器來(lái)說(shuō),支持靈活的定制,是生成能夠完全滿足要求的代碼的前提條件。
    XDoclet通過(guò)合并點(diǎn)(merge points)支持定制??合并點(diǎn)是在模板文件定義里允許運(yùn)行時(shí)插入定制代碼的地方。有時(shí)候,合并點(diǎn)甚至可以影響到全局代碼的生成,不但允許你添加一些定制內(nèi)容,還可以從根本上改變將要生成出來(lái)的東西。
    [定義:合并點(diǎn)(Merge points)是模板預(yù)先定義的允許你在代碼生成的運(yùn)行時(shí)加入定制內(nèi)容的擴(kuò)展點(diǎn)]
    讓我們研究一段從XDoclet源代碼里摘取出來(lái)的模板代碼。在為實(shí)體Bean生成主鍵的模板末尾,定義了這樣一個(gè)合并點(diǎn):
      <XDtMerge:merge file=”entitypk-custom.xdt”></XDtMerge:merge>
    如果你在你的merge目錄下創(chuàng)建了一個(gè)名為entitypk-custom.xdt文件,那么這個(gè)模板文件的內(nèi)容將會(huì)在這個(gè)合并點(diǎn)被包含進(jìn)來(lái)。你的定制可以執(zhí)行高層模板可以執(zhí)行的所有強(qiáng)大功能,可以進(jìn)行所有模板可以進(jìn)行的運(yùn)算(包括定義自定義標(biāo)簽,定義它們自己的合并點(diǎn))。
    上面的這種合并點(diǎn),為所有的類環(huán)境使用了同一個(gè)文件。當(dāng)然,也可以為每一個(gè)類環(huán)境使用不同的合并文件。如果你不想定制全部的類文件,或者你不想為了某些改動(dòng)而重寫模板的時(shí)候,這會(huì)很有用。不管動(dòng)機(jī)是什么,逐類的合并點(diǎn)很容易識(shí)別出來(lái):他們會(huì)在名字里包含一個(gè)XDoclet的逐類標(biāo)記{0}。這里有一個(gè)生成ejb-jar.xml文件里的安全角色引用的例子:
      <XDtMerge:merge file=”ejb-sec-rolerefs-{0}.xml”>
        <XDtClass:forAllClassTags tagName=”ejb:security-role-ref”>
          <security-role-ref>
            <role-name>
    <XDtClass:classTagValue
    tagName=”ejb:security-roleref”
    paramName=”role-name”/>
            </role-name>
            <role-link>
              <XDtClass:classTagValue
                tagName=”ejb:security-roleref”
                paramName=”role-link”/>
            </role-link>
          </security-role-ref>
        </XDtClass:forAllClassTags>
      </XDtMerge:merge>
    這段模板會(huì)遍歷工程里的所有Bean。對(duì)于每一個(gè)Bean,XDoclet先從Bean的文件名里提取出Bean名,然后替換{0},再根據(jù)替換后的文件名去尋找合并文件。例如,如果你有一個(gè)名為BlogFacadeBean的Bean,XDoclet會(huì)嘗試尋找一個(gè)名為ejb-src-rolerefs-BlogFacade.xml的合并文件。
    如果找不到這個(gè)合并文件,則這個(gè)<merge>標(biāo)簽的內(nèi)容模板會(huì)被解析。這意味著合并點(diǎn)不僅可以提供定制內(nèi)容,還可以在一個(gè)模板文件里定義一個(gè)替換點(diǎn),當(dāng)定制內(nèi)容不存在的時(shí)候使用替換點(diǎn)里的內(nèi)容。不是所有的XDoclet任務(wù)都提供了有替換內(nèi)容的合并點(diǎn),一般來(lái)說(shuō),它們更傾向于只提供一個(gè)簡(jiǎn)單的合并點(diǎn),僅僅當(dāng)合并文件存在的時(shí)候解析并導(dǎo)入合并文件的內(nèi)容。這取決于任務(wù)的開發(fā)者覺(jué)得哪種合并點(diǎn)更符合他的要求。
    還有一點(diǎn)沒(méi)有介紹到的是XDoclet如何定位合并文件,每一個(gè)XDoclet任務(wù)或者子任務(wù)都會(huì)提供一個(gè)mergeDir屬性,這個(gè)屬性用于設(shè)置你存放合并文件的目錄。

    posts - 4, comments - 5, trackbacks - 0, articles - 60

    Copyright © ikingqu

    主站蜘蛛池模板: 伊在人亚洲香蕉精品区麻豆| 人妻无码一区二区三区免费| 日本免费一二区在线电影| 天天爽亚洲中文字幕| 69av免费视频| 亚洲视频国产精品| 国产精彩免费视频| 亚洲一区二区观看播放| 日韩免费视频在线观看| 美女免费视频一区二区| 亚洲国产中文字幕在线观看| 久青草视频在线观看免费| 亚洲深深色噜噜狠狠爱网站| CAOPORN国产精品免费视频| 久久91亚洲精品中文字幕| 日韩在线永久免费播放| 亚洲午夜精品一区二区公牛电影院| 无码国产精品一区二区免费式直播 | 鲁丝片一区二区三区免费| 亚洲va在线va天堂va不卡下载| 日本免费人成视频在线观看| 亚洲一区二区三区免费观看| 午夜影视在线免费观看| 国产成人综合亚洲一区| 在线亚洲97se亚洲综合在线| 91av免费观看| 久久久久亚洲AV无码去区首 | 久久久无码精品亚洲日韩蜜桃| 91福利免费体验区观看区| 最新亚洲春色Av无码专区| 亚洲成AⅤ人影院在线观看| 免费观看久久精彩视频| 亚洲一区AV无码少妇电影| 中文字幕第13亚洲另类| 日韩免费人妻AV无码专区蜜桃| 国产AV旡码专区亚洲AV苍井空| 亚洲一级特黄大片无码毛片| 91高清免费国产自产| 免费人成视频在线播放| 亚洲精品成人图区| 亚洲第一黄色网址|