• <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>
            隨筆 - 181, 文章 - 2, 評論 - 85, 引用 - 0
            數(shù)據(jù)加載中……

            EJB 倡導(dǎo)者: 使用 Java EE 實(shí)現(xiàn)松耦合的 SOA 應(yīng)用程序

            本文探究了面向服務(wù)的體系結(jié)構(gòu)中各種形式的松耦合,并重點(diǎn)介紹什么時(shí)候是使用消息驅(qū)動 Bean 所提供的異步處理能力的最佳時(shí)機(jī)。

            摘自 IBM WebSphere 開發(fā)者技術(shù)期刊

            在每個(gè)專欄中,EJB 倡導(dǎo)者都采用獨(dú)特的前后銜接的對話方式與實(shí)際客戶和開發(fā)人員進(jìn)行交流,并在期間針對某一大家關(guān)注的設(shè)計(jì)問題推薦解決方案。其中并沒有介紹任何確定性的細(xì)節(jié),也沒有提出“新穎的”或?qū)S械捏w系結(jié)構(gòu)。要了解更多信息,請參見 EJB 倡導(dǎo)者簡介

            您對松耦合的定義是否太過狹窄呢?

            由于這是 2005 年的最后一篇文章,而且這次交流的是 Java? Platform、Enterprise Edition (Java EE) 組件而非會話和實(shí)體 Bean,所以可以通過這篇文章來很好地總結(jié)本專欄所進(jìn)行的一年之久的討論,并將所有的組件一起放到完整的面向服務(wù)的體系結(jié)構(gòu)中。







            問題:太過于關(guān)注 SOA 中的會話和實(shí)體

            親愛的 EJB 倡導(dǎo)者:

            到目前為止您的專欄全部都是關(guān)于服務(wù)的會話和實(shí)體 EJB,它對于直接連接 Java 應(yīng)用程序是很重要的,例如基于 Web 客戶端的 HttpServlets 或富(我們不喜歡說“胖”)客戶端的 Swing 應(yīng)用程序。但我們曾聽說面向服務(wù)的體系結(jié)構(gòu)都是與松耦合有關(guān)的。這不就意味著要盡可能地使用 SOAP 來提供使客戶端和服務(wù)器應(yīng)用程序能夠獨(dú)立運(yùn)行的語言中立性和異步協(xié)議?換句話說,為什么您對 JMS 和消息驅(qū)動 Bean 討論得不多呢?

            署名:
            Feeling Disconnected







            對松耦合有許多方面要考慮

            親愛的 Disconnected:

            EJB 倡導(dǎo)者關(guān)注的是應(yīng)用程序的服務(wù)層,而對客戶端介紹得很少,因?yàn)槲覍胖V語形式追隨功能 (form follows function) 深信不疑。

            其原因在于,許多進(jìn)行 SOA 的項(xiàng)目之所以失敗,是因?yàn)樗鼈儧]有首先建立定義服務(wù)的良好模型就開始著手實(shí)現(xiàn)細(xì)節(jié)。

            這種傾向相當(dāng)正常,因?yàn)槲以?SOA 項(xiàng)目中接觸到的大多數(shù)人都是架構(gòu)師和編程人員,他們知道棘手的始終是在細(xì)節(jié)上,想要盡快解決它們。所以,一旦我們認(rèn)同好服務(wù)的特征是粗粒度、無狀態(tài)、可通過中介傳遞和適應(yīng)的(請參閱 Is it ever best to use EJB components without facades in service oriented architectures?),很明顯帶有數(shù)據(jù)傳輸對象的會話 Bean 就會在實(shí)現(xiàn)中扮演重要角色。

            但上期專欄介紹了使用實(shí)體 Bean 及其 Home 方法代替會話 Bean 的可能性,從而使人們對會話 Bean 是否真的是必需的產(chǎn)生了疑問。圖 1 顯示了同時(shí)使用的兩種方法。


            圖 1. 用有待使用的會話和實(shí)體 EJB 實(shí)現(xiàn)的服務(wù)
            圖 1. 用有待使用的會話和實(shí)體 EJB 實(shí)現(xiàn)的服務(wù)

            圖 1 顯示了當(dāng)使用傳遞過去的會話 Bean 時(shí),純實(shí)體方法(自 EJB 2 開始可用)如何才能有更少的組件和更短的路徑長度。其中使用綠色框表示客戶端,藍(lán)色框表示各種接口和 Facade 類。橙色框是最常訪問的實(shí)體 Bean。框和框之間使用雙向箭頭連接,箭頭標(biāo)有在組件之間通信所使用的協(xié)議;藍(lán)色箭頭表示相同 JVM 中的 Java 調(diào)用,紅色箭頭表示遠(yuǎn)程連接(在本例中使用 RMI/IIOP)。為了表示端到端的流向,對流程箭頭進(jìn)行編號,其中 A1-A10 表示從 Java 客戶端經(jīng)過會話 Bean 到實(shí)體和返回的流程,B1-B4 表示從客戶端直接到實(shí)體 Bean 和返回的流程。

            客戶端用于檢索服務(wù)接口的編程模型也很簡單,雖然在圖中沒有表示出來。檢索會話 Bean 接口需要在 JNDI 上下文中查找會話 Home 并用它創(chuàng)建一個(gè)會話;實(shí)體 Home 僅僅需要一次查找,其方法可以直接調(diào)用而不需要?jiǎng)?chuàng)建對 EJB Object 的引用。以下兩段代碼示例顯示了它們之間的區(qū)別。


            清單 1. 定位和調(diào)用遠(yuǎn)程會話 EJB 方法
            												
            																		
            Context initCtx = new InitialContext();
            Object obj = initCtx.lookup("java:comp/env/ejb/OrderEntry");       
            OrderEntryHome home = (OrderEntryHome)PortableObjectRemote(
            	obj, OrderEntryHome.class
            );       
            OrderEntry ref = home.create();
            
            // Method must be invoked on a session reference
            CustomerData data = ref.getOpenOrderForCustomer(cID);
            
            												
            										


            清單 2. 定位和調(diào)用等效遠(yuǎn)程實(shí)體 EJB Home 方法
            												
            																		
            Context initCtx = new InitialContext();
            Object obj = initCtx.lookup("java:comp/env/Customer");
            CustomerHome ref = (CustomerHome)PortableObjectRemote(
            	obj, CustomerHome.class
            );
            
            // Note how the method is invoked directly   
            CustomerData data = ref.getOpenOrder(cID);
            
            												
            										

            圖 1 和相關(guān)的代碼示例顯示了 Java EE 編程模型的真正好處,不管您是否選擇使用實(shí)體 Home 方法。編程模型逐漸改進(jìn)并提供向后兼容。簡而言之,您的最佳實(shí)踐能夠得以發(fā)展而不必強(qiáng)制更改現(xiàn)有的應(yīng)用程序。另外,JNDI 上下文提供了一個(gè)不容忽視的松耦合相關(guān)方面:實(shí)現(xiàn)獨(dú)立性

            會話或?qū)嶓w EJB 組件的遠(yuǎn)程接口提供了位置獨(dú)立性。使用遠(yuǎn)程接口使得在相同的 JVM 中部署客戶端應(yīng)用程序和服務(wù)組件成為可能,其中它對系統(tǒng)(例如使用 HttpServlets 的 Web 應(yīng)用程序)的響應(yīng)時(shí)間、吞吐量和可維護(hù)性目標(biāo)有意義。圖 2 顯示的正是這樣的配置,其中企業(yè)質(zhì)量應(yīng)用服務(wù)器(如 IBM? WebSphere? Application Server)在聯(lián)合部署了客戶端和服務(wù)組件時(shí)“短路”遠(yuǎn)程接口以使用 Java 并按引用傳遞(不管服務(wù)實(shí)現(xiàn)為實(shí)體 Home 方法還是會話 Bean)。流程 A1-A6 顯示了與服務(wù)組件聯(lián)合部署的 HttpServlet 的使用。流程 B1-B4 顯示了它如何被遠(yuǎn)程富客戶端 Java EE 應(yīng)用程序重用。


            圖 2. 部署到本地 Web 應(yīng)用程序和遠(yuǎn)程富客戶端的服務(wù)
            圖 2. 部署到本地 Web 應(yīng)用程序和遠(yuǎn)程富客戶端的服務(wù)

            但這聽起來像是您已確定松耦合的最重要方面是語言中立性異步操作。并且您認(rèn)為需要異步操作會使得必須在服務(wù)器端使用消息驅(qū)動 Bean (MDB) 和 JMS。

            在實(shí)現(xiàn) MDB 時(shí),許多編程人員使用的方法是通過其遠(yuǎn)程接口調(diào)用表示服務(wù)的 EJB 組件,以使上述位置獨(dú)立性最大化。然后,不管服務(wù)實(shí)現(xiàn)是遠(yuǎn)程還是本地部署,MDB 的目的都是作為簡單的適配器,將 MQ 層連接到承載服務(wù)的 EJB 容器。JMS 可能由異步客戶端應(yīng)用程序(如果它是 Java)或 MDB 使用(通常用于應(yīng)答隊(duì)列)。圖 3 顯示了服務(wù)實(shí)現(xiàn)的另一個(gè)輸入通道的這一配置。


            圖 3. 用提供異步客戶端通道的 MDB 部署的服務(wù)
            圖 3. 用提供異步客戶端通道的 MDB 部署的服務(wù)

            流程 C1-C2 與 D1-D6 分別顯示,以闡釋客戶端和服務(wù)器流程的獨(dú)立性。C2 和 D6 只是對 Writer 是否寫入消息進(jìn)行“確認(rèn)”,并不意味著等待。清單 3 顯示了 MDB 的典型結(jié)構(gòu),該結(jié)構(gòu)應(yīng)該有助于闡明它必須做的處理:


            清單 3. 典型的消息驅(qū)動 Bean 實(shí)現(xiàn)
            												
            																		
            public class OrderSubmitMsgHandler implements MessageDrivenBean {
                private transient MessageDrivenContext context = null;
            
                // Interface supported by either the session Bean or entity Home
                private transient OrderEntry ref;
            
                public void ejbCreate() {
                    // Cache the home according to either snippet one or two
                }
                public void ejbRemove() {}
                public void setMessageDrivenContext(MessageDrivenContext mdc) {    
                    context = mdc; 
                }
                // Message acknowledge and database update participate
                public void onMessage(Message inMessage) {
                    // Parse the customer from the message
            	try {
            	    ref.submit(customer); 
            	} 
                    catch (CustomerDoesNotExist e) {
                        // Send JMS message to reply queue from exception
                    }
                    catch (OrderNotOpen e) {
                        // Send JMS message to reply queue from exception
                    }
                    catch (OrderHasNoItemsException e) {
                        // Send JMS message to reply queue from exception
                    }
                }
            }
            												
            										

            EJB 倡導(dǎo)者現(xiàn)在將回到您提到過的語言中立性問題。看起來您已經(jīng)將語言中立性的要求與異步處理的要求緊密聯(lián)系起來了。沒有理由不能將這些考慮分開;解析 SOAP 消息和用它調(diào)用會話 Bean 的能力應(yīng)該與該消息的處理是異步(通過 MQ 或者傳遞 JMS 等效消息的另一個(gè)協(xié)議)還是同步(例如通過 HTTP,甚至 IIOP)無關(guān)。事實(shí)上,Java EE 應(yīng)用程序上的一些早期“發(fā)明”的 Web 服務(wù)使用 HttpServlet 來解析通過 HTTP 傳遞的 XML 消息。這種方法最終發(fā)展為 SOAP/HTTP。圖 4 顯示可以在 EJB 組件所實(shí)現(xiàn)的服務(wù)之上提供的另一個(gè)路徑。


            圖 4. 將語言中立性和異步性的考慮分開
            圖 4. 將語言中立性和異步性的考慮分開

            Web Service Servlet 和 Message Driven Bean 可以共享對來自從消息串或 HttpServletRequest 提取的流的數(shù)據(jù)傳輸對象進(jìn)行解析的代碼。類似地,響應(yīng)或應(yīng)答可以共享從數(shù)據(jù)傳輸對象(它可以是 Exception 的一個(gè)實(shí)例)生成流的代碼。

            希望這有助于您理解 Java EE 組件的布置,所有這些都將提供某種對面向服務(wù)的體系結(jié)構(gòu)很基本的松耦合形式。

            對話到此結(jié)束,
            您的 EJB 倡導(dǎo)者







            仍然有太多選項(xiàng)要選擇

            親愛的 EJB 倡導(dǎo)者:

            謝謝。

            我以前不認(rèn)為像 JNDI 這樣的服務(wù)和遠(yuǎn)程接口會提供松耦合。我還可以了解如何將 SOAP 和 MQ 的概念“緊耦合”(按照您提到的方法),以及應(yīng)該如何盡可能將它們分開。所以將解析和生成 SOAP 消息看作由 Web 服務(wù) Servlet 和 MDB 重用的服務(wù)本身是很有意義的。

            但謝謝,我不要這樣。

            在這次討論之前,SOA 看似非常簡單:每個(gè)服務(wù)都公開一個(gè) SOAP/MQ 接口。現(xiàn)在看起來有好多選擇要考慮,并且既然將 SOAP 消息的解析和生成看作服務(wù),那么為什么不想建立一個(gè)獨(dú)立的會話 Bean 來封裝它們以便如圖中所顯示的那樣進(jìn)行重用呢?

            再次打擾您,我還是:
            Still Disconnected







            并非一切都是服務(wù):要使用業(yè)務(wù)模型加以判定

            親愛的 Disconnected:

            這次討論是當(dāng)過快要著手實(shí)現(xiàn)細(xì)節(jié)時(shí)會出現(xiàn)的情況的一個(gè)很好的例子。EJB 倡導(dǎo)者專欄 Which type of EJB component should assemble the data returned by a service? 非常重要,因?yàn)樗枋隽艘环N定義服務(wù)的自頂向下方法,這種方法將服務(wù)直接與業(yè)務(wù)流程模型相關(guān)聯(lián)。這里總結(jié)這種方法的基本細(xì)節(jié):

            1. 開發(fā)一個(gè)業(yè)務(wù)流程模型,顯示重要域?qū)ο蟮纳芷谥械闹饕锍瘫?/p>

              1. 我們使用狀態(tài)轉(zhuǎn)換關(guān)系圖來描述這一模型,其中狀態(tài)代表里程碑,轉(zhuǎn)換代表促使變成該狀態(tài)的事件。轉(zhuǎn)換可以看作應(yīng)用程序所提供的服務(wù)(有關(guān)示例請參見圖 5)。

              2. 我們使用 UML "Actor" 符號來擴(kuò)展?fàn)顟B(tài)轉(zhuǎn)換關(guān)系圖,以顯示當(dāng)處于該狀態(tài)時(shí)對象的所有者。狀態(tài)的所有者負(fù)責(zé)發(fā)起轉(zhuǎn)換,從而驅(qū)動應(yīng)用程序的安全模型(也請參見圖 5)。

              3. 對于業(yè)務(wù)流程中的每個(gè)狀態(tài),我們也對每個(gè)需要支持轉(zhuǎn)換動作的域?qū)ο蟮膶傩院退鼈冎g的關(guān)系進(jìn)行建模。我們通常使用的符號是 UML 類關(guān)系圖(有關(guān)示例,請參見圖 6)。為每個(gè)狀態(tài)建立獨(dú)立的關(guān)系圖可以讓我們隨時(shí)對變化的對象“形狀”進(jìn)行建模。這些關(guān)系圖驅(qū)動持久性數(shù)據(jù)。

            2. 開發(fā)一個(gè)用戶界面流程模型,顯示在典型“會話”期間來自業(yè)務(wù)流程的給定參與者如何與系統(tǒng)相交互。

              1. 與業(yè)務(wù)流程模型一樣,我們也使用狀態(tài)轉(zhuǎn)換關(guān)系圖,其中狀態(tài)代表屏幕和對話框,而轉(zhuǎn)換代表實(shí)際的 UI 事件,如選擇菜單項(xiàng)和按下按鈕。根據(jù)業(yè)務(wù)流程轉(zhuǎn)換指定與轉(zhuǎn)換相關(guān)的動作。

              2. 還是和業(yè)務(wù)流程模型一樣,我們構(gòu)建一個(gè)類關(guān)系圖來顯示必須在每個(gè)狀態(tài)中可見的數(shù)據(jù)以支持各種選擇。這意味著該數(shù)據(jù)必須可以從用戶輸入派生,并以自頂向下的方式驅(qū)動服務(wù)上的讀取操作。

              3. 與業(yè)務(wù)流程模型不同,我們不需要用 Actor 符號擴(kuò)展?fàn)顟B(tài)關(guān)系圖,因?yàn)殛P(guān)系圖本身可以視為單個(gè)用戶角色的“生命中的一天 (day in the life)”。


            圖 5. 顯示訂單生命周期的狀態(tài)轉(zhuǎn)換關(guān)系圖示例
            圖 5. 顯示訂單生命周期的狀態(tài)轉(zhuǎn)換關(guān)系圖示例

            圖 6. 顯示 open 訂單“形狀”的類關(guān)系圖示例
            圖 6. 顯示 open 訂單“形狀”的類關(guān)系圖示例

            這種綜合方法可以確保:

            • 將正確的操作分組到一個(gè)服務(wù)(與業(yè)務(wù)流程生命周期中的一個(gè)狀態(tài)相關(guān)聯(lián)的所有轉(zhuǎn)換和 read 方法)。

            • 每個(gè)服務(wù)的用途很好理解(根據(jù)相關(guān)業(yè)務(wù)對象來指定動作)。

            • 調(diào)用服務(wù)需要的前置條件和會產(chǎn)生的后置條件是相通的(當(dāng)前狀態(tài)和可選的監(jiān)護(hù)、以及下一狀態(tài)都是通過轉(zhuǎn)換指定的)。

            • 標(biāo)識了負(fù)責(zé)調(diào)用服務(wù)的用戶角色(參與者與每個(gè)狀態(tài)相關(guān)聯(lián))。

            不管是否實(shí)現(xiàn),方法簽名都不會提供此信息,但此信息對于好的 SOA 來說是很關(guān)鍵的。否則,編程人員將陷入另一種傾向:一旦有懷疑,就再次構(gòu)建。因?yàn)?SOA 的開發(fā)成本比較高(要為圖 4 所示的完全松耦合提供各種中介器和適配器),所以這種反對重用的傾向可能會導(dǎo)致獲得好處最少。

            對您關(guān)于簡單性的答復(fù)中提出的問題的回答是,此信息一點(diǎn)都沒有強(qiáng)制您以某種方式公開接口,EJB 倡導(dǎo)者知道簡單只存在于旁觀者眼中。如果您想要使服務(wù)開發(fā)人員不必進(jìn)行選擇,只需為每個(gè)服務(wù)提供圖 5 中所示的所有“藍(lán)色”組件即可:

            • 遠(yuǎn)程服務(wù)接口,用于提供同步 Java EE 客戶端訪問服務(wù)操作的位置獨(dú)立性。

            • 與每個(gè)操作相關(guān)聯(lián)的 MDB,通過遵循 JMS 的 MQ 實(shí)現(xiàn)來提供異步非 Java 客戶端訪問。您可以選擇編寫此 MDB 或不同的 MDB 以期待 JMS 客戶端的 Java 消息(從而避免 HTTP 解析開銷)。

            • 與每個(gè)操作相關(guān)聯(lián)的 Web 服務(wù) Servlet,用于提供同步 SOAP over HTTP 客戶端訪問。

            因?yàn)橛腥藭?dān)心這種方法將生成大量未使用的組件,所以另一種簡單的方法是,應(yīng)用 EJB 倡導(dǎo)者喜歡的內(nèi)容來調(diào)用面向客戶端的體系結(jié)構(gòu) (COA);以對客戶端最自然的方式給它們提供使用服務(wù)正好需要的內(nèi)容。

            這種 COA 方法需要考慮業(yè)務(wù)流程和 UI 模型的細(xì)節(jié),以便為每種方法挑選最可能的候選者。例如:

            • 業(yè)務(wù)流程生命周期中的狀態(tài)之間的轉(zhuǎn)換很可能是異步服務(wù)的候選者,因?yàn)樗鼈儗⑹窍嚓P(guān)域?qū)ο蟮摹八姓摺弊凅w。例如,在 open 訂單應(yīng)用程序(我們在上述示例中調(diào)用此 OrderEntry)中,submit 方法可以簡單地將訂單的狀態(tài)更改為“submitted”,并發(fā)送一條 JMS 消息來將其復(fù)制到已提交訂單應(yīng)用程序中(我們將這稱為一次 OrderFulfillment)。

            • 狀態(tài)間的轉(zhuǎn)換通常應(yīng)該是同步的,因?yàn)樗姓邲]有改變。舉個(gè)例子來說明為什么這些操作不應(yīng)該是異步的,設(shè)想一下,如果您進(jìn)入一位書商的 Web 應(yīng)用程序,還必須輪詢或等待發(fā)布-訂閱事件來顯示目錄或?qū)⑽锲诽砑拥劫徫镘囍校τ谙胍ㄟ^異步通道使用偽同步方式的讀者,請查閱 Bobby Woolf 關(guān)于設(shè)計(jì)消息傳遞系統(tǒng)的書籍。

            • 只有對于沒有相關(guān)的非 Java 客戶端和服務(wù)的集成場景,才提供 SOAP over HTTP 或 MQ。

            使用 COA 方法,可以“準(zhǔn)時(shí) (just-in-time)”開發(fā)組件,這就是 EJB 倡導(dǎo)者喜歡推薦它的原因。

            對您的問題(為什么不將所有的東西都看作是服務(wù),甚至是與中介器和適配器相關(guān)聯(lián)的轉(zhuǎn)換)的回答的最后一點(diǎn)是:簡單的回答超出了“過猶不及”這一事實(shí)。在開發(fā) SOA 或 COA Java EE 應(yīng)用程序時(shí),最好將服務(wù)視為業(yè)務(wù)流程模型上的操作。服務(wù)與應(yīng)用程序的功能需求有關(guān)。中介和相關(guān)聯(lián)的轉(zhuǎn)換與非功能需求有關(guān),例如可靠性、可用性、有效性、可維護(hù)性和可移植性。如果您將中介或相關(guān)聯(lián)的轉(zhuǎn)換視作第一個(gè)類服務(wù),則最終將使應(yīng)用程序的真實(shí)用途變得模糊。

            我知道這其中有很多方面的內(nèi)容需要理解,所以當(dāng)您應(yīng)用這些方法時(shí),遇到相關(guān)細(xì)節(jié)問題不要嫌麻煩,盡管與我聯(lián)系。

            對話到此結(jié)束,
            您的 EJB 倡導(dǎo)者







            結(jié)束語

            這些交流中談?wù)摿?Java EE 如何為采用面向服務(wù)的體系結(jié)構(gòu)的應(yīng)用程序提供完整的實(shí)現(xiàn)框架,其中每個(gè)組件或 API 都在一些“松耦合”方面扮演重要角色:

            • 操作系統(tǒng)獨(dú)立性是由 Java 本身提供的,因?yàn)?Java 為組件提供“一次編寫,到處運(yùn)行”的語言,使得您的代碼與基礎(chǔ)操作系統(tǒng)相分離。

            • 實(shí)現(xiàn)獨(dú)立性是由 Java Naming 和 Directory Interface (JNDI) 提供的,它具備在運(yùn)行時(shí)將邏輯名稱綁定到實(shí)現(xiàn)的能力。

            • 位置獨(dú)立性是由遠(yuǎn)程接口使用 RMI over IIOP 提供給無狀態(tài)會話 Bean 或封裝服務(wù)的實(shí)體 Home 方法的。RMI/IIOP 是一個(gè)相當(dāng)快的有狀態(tài)連接,但擴(kuò)展性不那么好。

            • Web 服務(wù)器獨(dú)立性是由 HttpServlets 提供的,它可以響應(yīng)同步 HTTP 協(xié)議。與 RMI/IIOP 不同的是,HTTP(通常)是一個(gè)擴(kuò)展性很好的無狀態(tài)協(xié)議,但由于消息大小的限制,而且每次都需要在客戶端和服務(wù)器之間建立和取消連接,所以不能執(zhí)行得很好。

            • 應(yīng)用獨(dú)立性是由異步 Java Messaging Service(或非 Java 客戶端的 MQ)和消息驅(qū)動 Bean 提供的(用于隊(duì)列處理程序)。

            • 語言獨(dú)立性是由標(biāo)準(zhǔn)消息格式(如 SOAP)提供的,不管它是在 RMI/IIOP、HTTP 還是 MQ 上傳遞。因此,SOAP 可以被每個(gè)組件使用,但只有在需要時(shí)才使用它,這一點(diǎn)很重要。

            相信您可以找到其他方法,我們樂意看到這樣的結(jié)果。困難的是需要處理與每種方法相關(guān)聯(lián)的權(quán)衡。這應(yīng)該能夠讓您忙到明年。

            posted on 2006-04-17 02:22 wsdfsdf 閱讀(205) 評論(0)  編輯 收藏 引用 所屬分類: 技術(shù)文章

            久久久青草青青国产亚洲免观| 久久久久亚洲av无码专区喷水| 人妻无码中文久久久久专区| 久久精品无码专区免费| 精品久久久久久亚洲| 久久亚洲国产成人精品性色| 亚洲色大成网站www久久九| 伊色综合久久之综合久久| 久久大香萑太香蕉av| 久久午夜免费视频| 一本色道久久综合| 免费精品久久天干天干| 亚洲乱码中文字幕久久孕妇黑人| 久久久久人妻精品一区| 东京热TOKYO综合久久精品| 国产精品一久久香蕉产线看 | 久久久久国色AV免费观看| 国产激情久久久久影院小草 | 精品久久无码中文字幕| 国产产无码乱码精品久久鸭| 久久精品一区二区| 久久久久九国产精品| 久久AV高潮AV无码AV| 久久精品天天中文字幕人妻| 免费观看久久精彩视频| 久久精品成人免费观看97| 久久午夜无码鲁丝片秋霞| 国产成人久久激情91| 欧美亚洲另类久久综合婷婷| 99久久国产精品免费一区二区| 国产精品毛片久久久久久久| 日本精品久久久久影院日本| 亚洲欧美伊人久久综合一区二区 | 国内精品伊人久久久久影院对白| 狠狠色伊人久久精品综合网 | 国产精品99久久99久久久| 国产精品激情综合久久| 亚洲精品午夜国产VA久久成人| 大香网伊人久久综合网2020| 久久99久国产麻精品66| 99久久99久久精品国产片|