j2ee應(yīng)用下基于aop的抓取策略實(shí)現(xiàn)_第1頁(yè)
j2ee應(yīng)用下基于aop的抓取策略實(shí)現(xiàn)_第2頁(yè)
j2ee應(yīng)用下基于aop的抓取策略實(shí)現(xiàn)_第3頁(yè)
j2ee應(yīng)用下基于aop的抓取策略實(shí)現(xiàn)_第4頁(yè)
j2ee應(yīng)用下基于aop的抓取策略實(shí)現(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩4頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、j2ee應(yīng)用下基于aop的抓取策略實(shí)現(xiàn)data fetching使用了 o/r mapping i具的典型j2ee應(yīng)用都會(huì)面臨這樣一個(gè)問(wèn)題:如何通過(guò)最精簡(jiǎn)的sql杳詢獲取所需的數(shù)據(jù)。很多時(shí)候這可不是輕而易舉的事悄。默認(rèn)悄況下,o/r mapping 工具會(huì)按需加載數(shù)據(jù),除非你改變了其默認(rèn)設(shè)置。延遲加載行為保證了依賴的數(shù)據(jù)只有在真 正請(qǐng)求時(shí)才會(huì)彼加載進(jìn)來(lái),這樣就可以避免創(chuàng)建無(wú)謂的對(duì)彖。冇時(shí)我們的業(yè)務(wù)并不會(huì)使用到 依賴的那些組件,這吋延遲加載就派上用場(chǎng)了,同吋也無(wú)需加載那些用不上的組件了。典型情況卜',我們的業(yè)務(wù)很清楚需要哪些數(shù)據(jù)。但由于使用了延遲加載,在執(zhí)行大量select 查詢時(shí)數(shù)據(jù)庫(kù)

2、的性能會(huì)降低,因?yàn)闃I(yè)務(wù)所需的數(shù)據(jù)并不是一下子獲得的。這樣,對(duì)于那些需 要支持大量請(qǐng)求的應(yīng)用來(lái)說(shuō)町能會(huì)產(chǎn)生瓶頸(可伸縮性問(wèn)題)。來(lái)看個(gè)例子吧,假設(shè)某個(gè)業(yè)務(wù)流程想耍得到一個(gè)person及其address信息。我們將 address組件配置成延遲加載,這樣要想得到所需的數(shù)據(jù)就需要更多的sql查詢,也就是 說(shuō)首先查詢person,然后再查詢address。這增加了數(shù)據(jù)庫(kù)ai應(yīng)用z間的通信成本。解 決辦法就是在一個(gè)單獨(dú)的查詢中將person和address都得到,因?yàn)槲覀冎肋@兩個(gè)組件 都是業(yè)務(wù)流程所需的。如果在dao/repository及底層service開(kāi)發(fā)特定于業(yè)務(wù)的fetching-api,對(duì)

3、于那 些擁有不同數(shù)據(jù)集的相同領(lǐng)域?qū)﹀鑱?lái)說(shuō),我們就得編寫(xiě)不同的api進(jìn)行抓収并組裝了。這 么做會(huì)使repository及底層service過(guò)于膨脹,最終變成維護(hù)的夢(mèng)魘。延遲抓取的另一個(gè)問(wèn)題就是在獲収到請(qǐng)求的數(shù)據(jù)詢要一直打開(kāi)數(shù)據(jù)庫(kù)連接,否則應(yīng)用就會(huì)拋 出一個(gè)延遲加載異常。說(shuō)明:如果在查詢屮使用預(yù)先抓取來(lái)獲取二級(jí)緩存屮的數(shù)據(jù)時(shí),我們將無(wú)法解決上面提出的 問(wèn)題。對(duì)于hibwte來(lái)說(shuō),如果我們使用預(yù)先抓収來(lái)獲取二級(jí)緩存中的數(shù)據(jù),那么它將 從數(shù)據(jù)幷而不是緩存屮去獲取數(shù)據(jù),哪怕是二級(jí)緩存屮已經(jīng)存在該數(shù)據(jù)。這就說(shuō)明hibernate也沒(méi)有解決這個(gè)問(wèn)題,從而表明我們不應(yīng)該在查詢中通過(guò)預(yù)先抓収來(lái)獲得二級(jí) 緩存屮的

4、對(duì)象。對(duì)于那些可以訃我們調(diào)節(jié)查詢以獲取緩存對(duì)象的0/r mapping i具來(lái)說(shuō),如果緩存屮有 対象就會(huì)從緩存中獲収,否則采収預(yù)先抓取的方式。這就解決了上血提到的事務(wù)/de連接問(wèn) 題,因?yàn)樵诓樵兊膱?zhí)行過(guò)程中會(huì)同時(shí)獲取緩存中的數(shù)據(jù)而不是按需讀?。ㄒ簿褪茄舆t加載)。通過(guò)f面的示例代碼來(lái)了解一下延遲加載所面對(duì)的問(wèn)題及解決辦法??紤]如下場(chǎng)景:某領(lǐng)域 中有 3 個(gè)實(shí)體,分另lj是 employee、department s dependent。這三個(gè)實(shí)體之間的關(guān)系如下: employee 有 0 或多個(gè) dependents。 department 冇 0 或多個(gè) employees。 employee

5、 屬于 0 或 1 個(gè) department«我們要執(zhí)行三個(gè)操作:1.獲収employee的詳細(xì)信息。2獲取employee及其dependent的詳細(xì)信息。3獲取employee及其department的詳細(xì)信息。以上三個(gè)操作需要獲取并呈現(xiàn)不同的數(shù)據(jù)。使川延遲加載有如卜弊端: 如果對(duì)實(shí)休employee所關(guān)聯(lián)的dependent和department這兩個(gè)實(shí)體使用延 遲加載,那么在操作2和3中就會(huì)生成更多的sql查詢語(yǔ)句。在多個(gè)杳詢語(yǔ)句的執(zhí)行過(guò)程屮需要保持?jǐn)?shù)據(jù)庫(kù)連接,否則會(huì)拋出一個(gè)延遲加載異常, 這將導(dǎo)致數(shù)據(jù)出現(xiàn)問(wèn)題。但期一方面,使用預(yù)先抓取也存在如下弊端: 對(duì)employee所對(duì)

6、應(yīng)的dependents和department采取預(yù)先抓取會(huì)產(chǎn)牛不必要 的數(shù)據(jù)。無(wú)法在特定的場(chǎng)景下對(duì)查詢進(jìn)行調(diào)優(yōu)。在repository/dao或底層服務(wù)屮使用特定于操作的api可以解決上述問(wèn)題,但卻會(huì)導(dǎo) 致如下問(wèn)題: 代碼膨脹一不管是service還是repository/dao類(lèi)都無(wú)法幸免。 維護(hù)的夢(mèng)魘一不管是service還是repository/dao層,只要有新的操作都需 要增加新的apio代碼重復(fù)一有吋底層服務(wù)需要在獲取的實(shí)體上增加某些業(yè)務(wù)邏輯,與z類(lèi)似,還耍 在數(shù)據(jù)返回前檢查dao/repository層的查詢響應(yīng)以驗(yàn)證數(shù)據(jù)可用性。為了解決上面這些問(wèn)題,repository/da

7、o層需要根據(jù)不同的業(yè)務(wù)情況執(zhí)行不同的查詢來(lái) 獲取實(shí)體。就像aspect類(lèi)所定義的那樣,我們可以根據(jù)特定的操作使用不同的抓取機(jī)制 來(lái)覆蓋repository/dao類(lèi)所定義的默認(rèn)抓取模式。所有的抓取模式類(lèi)都實(shí)現(xiàn)了相同的接 口。«mefe*ce>o employeefetchingstralegy ccm »etchstr«tergy 0 qmerymp*oyeebyw()g employeefetchingstrategylmpiccrn 1«ciirgstr«tergy fdchingpmjern irplo querymptoyeekk

8、)g employeewithdepartmentfetchingstrategycom fetchtmjstr ater jy fetchr>a«ef n imp*q cjerym0oree&ykio一一_ i . 一.g employeewithdependentfetchingstrategycom fetchngssraitergry tetchrawern>r<)io c«r>ntoye«byworepository類(lèi)使用了上述的抓取模式來(lái)執(zhí)行杏詢,如下代碼所示:publie employee findemployeeby

9、ld(int employeeld) list employee =hibernatetemplate.find(fetchingstrategyqueryemployeebyid(),new integer (employeeld);if(employeesize() = 0)return null;return (employee)employee.get(0);)repository類(lèi)中的employee的抓収策略需耍根據(jù)實(shí)際怙:況進(jìn)行調(diào)整。我們決定將 repository層的抓取策略調(diào)整到repository和service層夕卜,放在一個(gè)aspect類(lèi) 屮,這樣當(dāng)需要增加新的業(yè)務(wù)邏輯

10、時(shí)只需修改aspect類(lèi)并增加一個(gè)針對(duì)于repository 的抓取策略實(shí)現(xiàn)即可。這里我們使川了面向方面的編程(aspect oriented programming) 以根據(jù)業(yè)務(wù)的不同使用不同的抓取策略。什么是面向方面的編程?而向方而的編程(aop)可以通過(guò)模塊化的形式實(shí)現(xiàn)實(shí)際應(yīng)用中的橫切關(guān)注點(diǎn),如日志、追 蹤、動(dòng)態(tài)分析、錯(cuò)課處理、服務(wù)水平協(xié)議、策略增強(qiáng)、池化、緩存、并發(fā)控制、安全、事務(wù) 管理以及業(yè)務(wù)規(guī)則等等。對(duì)這些關(guān)注點(diǎn)的傳統(tǒng)實(shí)現(xiàn)方式需要我們將這些實(shí)現(xiàn)融合到模塊的核 心關(guān)注點(diǎn)中。憑借aop,我們可以在一個(gè)叫做方血(aspect)的獨(dú)立模塊屮實(shí)現(xiàn)這些關(guān)注 點(diǎn)。模塊化的結(jié)果就是設(shè)計(jì)簡(jiǎn)化、易于理

11、解、質(zhì)量捉升、開(kāi)發(fā)吋間降低以及對(duì)系統(tǒng)需求變更 的快速響應(yīng)。接下來(lái)讀者朋友們口j以參考ramnivas laddad所著的aspectj in action一書(shū)以 詳細(xì)了解aspect j的概念以及編程方式,還可以了解一下aspect j的開(kāi)發(fā)工具。aspect在抓取策略實(shí)現(xiàn)上扮演著璽要角色。抓取策略是個(gè)業(yè)務(wù)層的橫切關(guān)注點(diǎn),它會(huì)隨著 業(yè)務(wù)的變化而變化o aspect對(duì)于特定的業(yè)務(wù)邏輯下使用何種抓収策略起到了至關(guān)重要的作 用。這里我們將對(duì)抓取策略的管理放在了底層服務(wù)和respository層之外。任何新的業(yè) 務(wù)都可能需要不同的抓取策略,這樣我們就無(wú)需修改底層服務(wù)或是respos辻。ry層的api

12、就能應(yīng)用新的抓取策略了。fetchingstrategyaspect aj/ * *identify the get empl oy eewi t hdepart men t det ails flow where you need to change the fetchingstrategy at repository level*/pointcut empwithdepartmentdetail() : call (*employeerepositoryf indemployeebyid(int)&& cflow(execution (*employeedetdilsser

13、vicegetemployeewithdepartmentdetails(int);/ * *when you are at the specified poincut before continuing further update the fetchingstrategy inemployeerepositoryimp1 toemployeewithdepartmentfetchingstrategy*/before(employeerepositoryimpl r) : empwithdepartmentdetai丄() &&target(r)rfetchingstrat

14、egy = new employeewithdepartmentfetchingstrategy();/ identify the getemployeewithdependentdetails flow where you need to change the fetchingstaratergy at repository level*/pointcut empwithdependentdetail () : call (*employeerepositoryf indemployeebyid(int)&& cflow (execution (*employeedetail

15、sservice.getemployeewithdependentdetails(int);when you are at the specified poincut before continuing further update the fetchingstrategy inemployeerepositorylmpl to employeewithdependentfetchingstrategy */before(employeerepositorylmpl r): empwithdependentdetail() &&target (r)r.fetchingstrat

16、egy = new employeewithdependentfetchingstrategy ();這樣depository至u底要執(zhí)行何種查詢就不是由service和repository層所決定了, 而是由外面的aspect決定,縱使增加新的業(yè)務(wù)也無(wú)盂修改底層服務(wù)和repository層。 決定執(zhí)行何種杏詢的邏輯就成為一個(gè)橫切關(guān)注點(diǎn)了,它被放在aspect屮。aspect會(huì)根據(jù) 業(yè)務(wù)規(guī)則的不同在service層調(diào)用repository層的api之前將抓取策略注入到 repository屮。這樣我們就可以使用相同的service和repository層api來(lái)滿足各 種不同的業(yè)務(wù)規(guī)則了。來(lái)看

17、個(gè)具休示例吧,該示例會(huì)同時(shí)抓取個(gè)employee的department和dependent的 詳細(xì)信息。我們需要對(duì)業(yè)務(wù)層進(jìn)行一些變更,增加一個(gè)方法: getemployeewithdepartmentanddependentsdetails (int employeeld)。實(shí)現(xiàn) 新的抓取策略類(lèi) employeewithdepartme nt anddependent fetchings tar a tergy, 后者又實(shí)現(xiàn)了 employeefetchingstrategyqueryemp丄oyeebyid 方法,該方法會(huì)返回優(yōu)化后的查詢,可以在一個(gè)sql語(yǔ)句中獲取所需數(shù)據(jù)。由aspect將

18、匕述的抓取策略注入到相關(guān)的業(yè)務(wù)中,如下所示:pointcut empwithdependentanddepartmentdetail () : call (*employeerepository.findemployeebyid(int)&& cflow (execution (*employeedetailsservice.getemployeewithdepartmentanddependentsdeta ils (int);before(employeerepositoryimpl r):empwithdependentanddepaetmentdetai丄()&

19、& target(r)r.fetchingstrategy = newemployeewithdepartmentanddependentfetchingstaratergy();如你所見(jiàn),我們并沒(méi)有修改底層業(yè)務(wù)與repository層而是使用aspect和一個(gè)新的 fetchingstrategy實(shí)現(xiàn)就完成了上述新增的業(yè)務(wù)?,F(xiàn)在我們來(lái)談?wù)勱P(guān)于二級(jí)緩存的查詢優(yōu)化問(wèn)題。在上面的示例代碼中,我們對(duì)department 實(shí)體進(jìn)行一些修改并配置在二級(jí)緩存中。如果對(duì)department實(shí)體采取預(yù)先抓取,那么對(duì) 于同樣的department實(shí)例,縱使它位于二級(jí)緩存中,每次也都需要查詢數(shù)據(jù)庫(kù)。如果不

20、 在査詢中獲取department實(shí)體,那么業(yè)務(wù)層就需耍參與到事務(wù)當(dāng)中,因?yàn)槲覀儾](méi)有將 department實(shí)體緩存起來(lái)而是通過(guò)延遲加載的方式得到它。這樣,事務(wù)聲明就從底層移到了業(yè)務(wù)層,雖然我們知道該業(yè)務(wù)需要哪些數(shù)據(jù),但0/r mapping工具卻沒(méi)有提供相應(yīng)的機(jī)制來(lái)解決上而遇到的問(wèn)題,即預(yù)先抓収緩存中的數(shù)據(jù)。對(duì)于那些沒(méi)有緩存的數(shù)據(jù)來(lái)說(shuō)這種方式?jīng)]什么問(wèn)題,但對(duì)于緩存數(shù)據(jù)來(lái)說(shuō),這就依賴于0/r mapping工具了,因?yàn)橹挥兴拍芙鉀Q緩存數(shù)據(jù)問(wèn)題。該示例附帯的源代碼詳細(xì)解釋了抓取策略。該zip文件含有一個(gè)工程示例,闡述了上面談 到的所冇場(chǎng)景。你可以使用任何ide或是使用aspectj編譯器從命令行執(zhí)行代碼。在執(zhí)行 詢請(qǐng)確保jd

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論