2023年全國(guó)碩士研究生考試考研英語(yǔ)一試題真題(含答案詳解+作文范文)_第1頁(yè)
已閱讀1頁(yè),還剩29頁(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、<p><b>  引言</b></p><p>  框架從某種意義上講是某種應(yīng)用的半成品,它是由一組組件所構(gòu)成。對(duì)于程序的重用性與所設(shè)計(jì)的系統(tǒng)的擴(kuò)展性以達(dá)到開(kāi)發(fā)周期的縮減的目的與開(kāi)發(fā)質(zhì)量的提高等目的,往往是框架一直追求并良好的實(shí)現(xiàn)了的。</p><p>  在軟件設(shè)計(jì)中,最終遵循的還是一個(gè)設(shè)計(jì)理念,就是“高內(nèi)聚,低耦合”??蚣芤话闶菍?wèn)題分割成若干子問(wèn)題進(jìn)

2、行一一攻破,從而起到易于控制、擴(kuò)展,易于分配資源的效果。設(shè)計(jì)過(guò)程中,常常引入“層”的概念,及將各個(gè)義務(wù)分層實(shí)現(xiàn)。其間難免會(huì)出現(xiàn)耦合,而耦合度過(guò)高會(huì)降低系統(tǒng)的擴(kuò)展性和維護(hù)性。而框架主要工作在層與層之間,很好的解決了這一問(wèn)題。在軟件設(shè)計(jì)中有一個(gè)概念叫做IoC,及控制反轉(zhuǎn),也叫DI(依賴(lài)注入),它主要就是實(shí)現(xiàn)層與層之間的松耦合。</p><p>  面向?qū)ο缶幊淘谲浖O(shè)計(jì)中無(wú)處不在,非常完美的解決了代碼重用。但有時(shí)候具

3、體的業(yè)務(wù)貫穿整個(gè)系統(tǒng),而往往這個(gè)業(yè)務(wù)是重復(fù)出現(xiàn)的,利用面向?qū)ο笠巡荒芎芎媒鉀Q。在這里便出現(xiàn)了AOP(面向切面編程),將其中相同的業(yè)務(wù)抽取出來(lái)進(jìn)行統(tǒng)一解決。在這里不得不說(shuō)一下Spring框架的強(qiáng)大魅力,Spring對(duì)IoC和AOP的操作可謂前無(wú)古人。</p><p>  本文主要利用IoC和AOP的概念,解決層與層之間的依賴(lài)關(guān)系以及重復(fù)業(yè)務(wù)的處理。</p><p><b>  研究

4、背景</b></p><p>  上世紀(jì)末與本世紀(jì)初,J2EE開(kāi)始盛行,主要?dú)w功于它對(duì)中間層概念提出了系統(tǒng)性標(biāo)準(zhǔn)。但事實(shí)上,它并沒(méi)有取得實(shí)質(zhì)性的成功,原因主要是因?yàn)椴还軓钠湫?、難度還是性能上來(lái)講都不孚眾望。</p><p>  在J2EE早期階段,都是利用EJB技術(shù)來(lái)開(kāi)發(fā)J2EE應(yīng)用的。但是,對(duì)于EJB,其學(xué)習(xí)成本非常高也難于理解,而且要想應(yīng)用EJB技術(shù)也是相當(dāng)困難的。因?yàn)镋

5、JB強(qiáng)制程序員必須依照它的規(guī)范去繼續(xù)各種不同的接口,這樣便會(huì)導(dǎo)致代碼冗余及相似。此外對(duì)于其配置既是紛繁復(fù)雜又是味同嚼蠟。對(duì)于使用JNDI查找對(duì)象也是如此。雖然xdoclet的應(yīng)運(yùn)而生和緩了其中部分的開(kāi)發(fā)工作,但是EJB存在的各大問(wèn)題都造成了對(duì)其使用的不方便性。隨著Java語(yǔ)言的發(fā)展,AOP和IoC等技術(shù)的逐漸成熟,一種新的J2EE解決方案應(yīng)運(yùn)而生,即輕量級(jí)框架。[1]</p><p><b>  研究平

6、臺(tái)</b></p><p>  本文主要是基于Eclipse平臺(tái),使用Java語(yǔ)言編寫(xiě)IoC和AOP的實(shí)現(xiàn)程序。</p><p><b>  Java語(yǔ)言</b></p><p>  Java是一種面向?qū)ο蟮?,由Sun公司開(kāi)發(fā)的程序設(shè)計(jì)語(yǔ)言,具體研發(fā)是James Gosling及其同事,在上世紀(jì)90年代末正式推出。Java的強(qiáng)大之處

7、在于其跨平臺(tái)性,可在不同操作系統(tǒng)上編寫(xiě)應(yīng)用軟件。Java語(yǔ)言不同于其他編程語(yǔ)言,其優(yōu)勢(shì)主要體現(xiàn)在它具有通用、高效、安全等優(yōu)點(diǎn)。而且該語(yǔ)言的應(yīng)用領(lǐng)域也極其廣泛。在微型電腦、數(shù)據(jù)中心、超級(jí)計(jì)算機(jī)以及各種網(wǎng)頁(yè)應(yīng)用等都能見(jiàn)到Java的身影。雖然Java的編程風(fēng)格與之C、C++非常接近,但與C語(yǔ)言不同的是,Java是完全的面相對(duì)象,對(duì)于C++核心的面向?qū)ο蠹夹g(shù)它也是完美的繼承了。同時(shí),Java一改C中指針的概念,取而代之的是引用的概念。同時(shí)也摒棄

8、了C中運(yùn)算符重載和多繼承等特征。在此基礎(chǔ)上,Java也增加了自己的新特性,就是垃圾回收機(jī)制,對(duì)于不再引用而又一直在內(nèi)存中的引用進(jìn)行回收處理。程序員也從中得益而不用手動(dòng)進(jìn)行內(nèi)存管理。</p><p><b>  Eclipse</b></p><p>  Eclipse是一個(gè)開(kāi)源的軟件開(kāi)發(fā)工具,同時(shí)也是功能完備,能進(jìn)行商用的工業(yè)開(kāi)發(fā)平臺(tái)。主要組成為Eclipse項(xiàng)目、工

9、具項(xiàng)目、技術(shù)項(xiàng)目,具體是指Eclipse Platform,JDT,CDT,PDE。其中,Eclipse Platform是可擴(kuò)展的集成開(kāi)發(fā)環(huán)境;JDT是Java開(kāi)發(fā)工具,主要用于Java開(kāi)發(fā);CDT是C語(yǔ)言開(kāi)發(fā)工具,主要用于C開(kāi)發(fā);PDE則是對(duì)插件的開(kāi)發(fā)。Eclipse為構(gòu)建IDE和建造塊建立堅(jiān)實(shí)的基礎(chǔ)。對(duì)于Eclipse Platform,它允許第三方工具的無(wú)縫對(duì)接,從而起到無(wú)須辨別具體工具的功能體現(xiàn)在哪里的作用。</p>

10、;<p><b>  IoC和AOP</b></p><p><b>  IoC(控制反轉(zhuǎn))</b></p><p>  IoC,英文全稱(chēng)為Inversion of Control,及控制反轉(zhuǎn),主要用于降低程序間的耦合度。控制反轉(zhuǎn)一般分為兩種類(lèi)型,依賴(lài)注入(Dependency Injection,簡(jiǎn)稱(chēng)DI)和依賴(lài)查找(Depend

11、ency Lookup)。依賴(lài)注入應(yīng)用比較廣泛。[2]</p><p><b>  依賴(lài)注入</b></p><p>  依賴(lài)注入就是容器全權(quán)負(fù)責(zé)組件,給予其回調(diào)接口和上下文條件。EJB和Apache Avalon 都使用這種方式。如此看來(lái),對(duì)于依賴(lài)對(duì)象的查找以及資源的查找就必須使用容器提供的接口,控制反轉(zhuǎn)也就體現(xiàn)在了回調(diào)接口上。容器提供應(yīng)用代碼資源也是通過(guò)回調(diào)接口的

12、。 [3]</p><p><b>  實(shí)現(xiàn)方式</b></p><p>  對(duì)于依賴(lài)注入,主要的實(shí)現(xiàn)方式分別為接口注入(Interface Injection)、Set方法注入(Setter Injection)和構(gòu)造注入(Constructor Injection)。[4]</p><p><b>  接口注入</b>

13、</p><p>  在接口中定義要注入的信息再通過(guò)接口來(lái)完成此功能就叫接口注入。具體示例如下:</p><p>  編寫(xiě)一個(gè)IBiz接口,Dao層的注入將通過(guò)這個(gè)接口進(jìn)行。假設(shè)該接口中有一getDao()方法,用于獲取數(shù)據(jù)訪問(wèn)層的對(duì)象。</p><p>  public interface IBiz{</p><p><b>  

14、/**</b></p><p>  * @param dao 數(shù)據(jù)訪問(wèn)層對(duì)象</p><p><b>  */</b></p><p>  public void getDao(Dao dao);</p><p><b>  }</b></p><p>  對(duì)于想

15、要進(jìn)行數(shù)據(jù)庫(kù)操作的類(lèi)就必須得實(shí)現(xiàn)IBiz接口,業(yè)務(wù)邏輯類(lèi)Biz實(shí)現(xiàn)這個(gè)接口IBiz。</p><p><b>  /*</b></p><p>  * 具體實(shí)現(xiàn)IBiz接口的類(lèi),重寫(xiě)了getDao方法</p><p><b>  */</b></p><p>  public class Biz i

16、mplements IBusiness{</p><p>  private Dao dao;</p><p><b>  @Override</b></p><p>  public void getDao(Dao dao){</p><p>  this.dao=dao;</p><p>&l

17、t;b>  }</b></p><p><b>  }</b></p><p>  只有實(shí)現(xiàn)IBiz接口才能完成依賴(lài)注入。</p><p><b>  Set方法注入</b></p><p>  Set方法注入就是在需要屬性注入的類(lèi)中定義一個(gè)Set方法,并設(shè)置注入元素為其參數(shù)。&l

18、t;/p><p>  假設(shè)業(yè)務(wù)層Biz依賴(lài)數(shù)據(jù)訪問(wèn)層,且持有其屬性,需定義一個(gè)Set方法來(lái)接受數(shù)據(jù)訪問(wèn)層的注入。</p><p>  public class Biz{</p><p>  //數(shù)據(jù)訪問(wèn)層對(duì)象的引用</p><p>  private Dao dao;</p><p>  public void setDa

19、o(Dao dao){</p><p>  this.dao=dao;</p><p><b>  }</b></p><p>  //其他調(diào)用數(shù)據(jù)訪問(wèn)層的方法及其他操作</p><p><b>  }</b></p><p><b>  構(gòu)造注入</b>

20、;</p><p>  構(gòu)造注入就是在需要屬性注入的類(lèi)中提供一個(gè)有參構(gòu)造,其參數(shù)就是注入的元素。假設(shè)業(yè)務(wù)層Biz依賴(lài)數(shù)據(jù)訪問(wèn)層,且持有其屬性,可通過(guò)一個(gè)構(gòu)造器來(lái)接受數(shù)據(jù)訪問(wèn)層的注入。</p><p>  public class Biz{</p><p>  private Dao dao;</p><p>  public Biz(Dao

21、dao){</p><p>  this.dao=dao;</p><p><b>  }</b></p><p>  //其他調(diào)用數(shù)據(jù)訪問(wèn)層的方法及其他操作</p><p><b>  }</b></p><p><b>  IoC圖解</b><

22、/p><p>  AOP(面向切面編程) </p><p>  AOP就是Aspect Oriented Programming的縮寫(xiě),意為:面向切面編程。具體是指它是一種通過(guò)預(yù)編譯和動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的技術(shù)。[5]AOP是OOP的延續(xù),是軟件開(kāi)發(fā)中的一個(gè)熱點(diǎn),是函數(shù)式編程的一種衍生范型。AOP技術(shù)可以使業(yè)務(wù)邏輯的各個(gè)功能模塊耦合度降低,從而達(dá)到提高程序的重用性和開(kāi)發(fā)效率。 [

23、6]</p><p><b>  實(shí)現(xiàn)技術(shù)</b></p><p>  對(duì)于AOP技術(shù)的實(shí)現(xiàn),主要可通過(guò)以下兩種方式實(shí)現(xiàn):一種是動(dòng)態(tài)代理,對(duì)原有對(duì)象的行為通過(guò)截取消息,修飾消息,最終執(zhí)行修飾后的行為;另一種是靜態(tài)織入,以特定語(yǔ)法創(chuàng)建切面,以達(dá)到編譯器在編譯期織入切面代碼的目的。[7]然而殊途同歸,實(shí)現(xiàn)AOP的技術(shù)特性卻是相同的,分別為:</p><

24、p>  join point(連接點(diǎn)):連接點(diǎn)是程序運(yùn)行過(guò)程中具體的執(zhí)行點(diǎn),比如它 可以是一個(gè)方法。對(duì)于連接點(diǎn)并不是一個(gè)具體的概念,所以在是實(shí)現(xiàn)AOP時(shí)并不用去定義它。</p><p>  point cut(切入點(diǎn)):對(duì)于切入點(diǎn)這個(gè)概念,它實(shí)質(zhì)上是一個(gè)捕獲連接點(diǎn)的一種結(jié)構(gòu)。所以在實(shí)現(xiàn)AOP中,可通過(guò)定義一個(gè)切入點(diǎn)來(lái)攔截相關(guān)方法的調(diào)用。</p><p>  advice(通

25、知):本質(zhì)上是切入點(diǎn)是執(zhí)行程序,具體執(zhí)行切面的邏輯。</p><p>  aspect(方面):切點(diǎn)與通知合稱(chēng)切面,雖與面向?qū)ο笾械念?lèi)相似,但它更多的表達(dá)的是對(duì)象間的橫向關(guān)系。</p><p>  introduce(引入):以附加屬性方法的形式達(dá)到修改對(duì)象結(jié)構(gòu)的目的。有的AOP工具又將其稱(chēng)為mixin。</p><p><b>  主要目的</b&

26、gt;</p><p>  對(duì)于AOP的主要目的大致可分為事務(wù)處理、性能監(jiān)測(cè)、日志記錄、安全控制等。[8]</p><p><b>  主要意圖</b></p><p>  對(duì)邏輯代碼中事務(wù)處理、性能監(jiān)測(cè)、日志記錄、安全控制等的處理從中分離,重新獨(dú)立到非向?qū)I(yè)務(wù)方法中。此等做法的好處是在修改這些代碼的時(shí)候不影響業(yè)務(wù)邏輯,進(jìn)一步體現(xiàn)了軟件開(kāi)發(fā)的“

27、開(kāi)閉原則”。[9]</p><p>  注解(Annotation)</p><p>  Annotation(注解)是JDK5.0及以后版本引入的。對(duì)于注解,主要作用大致是監(jiān)測(cè)代碼依賴(lài)性,創(chuàng)建文檔,通過(guò)注解甚至可以執(zhí)行基礎(chǔ)的編譯檢查。[10]注解的編寫(xiě)方式是以“@”開(kāi)頭加上自定義的注解名,通過(guò)其參數(shù)個(gè)數(shù)的不同,大致可分為三類(lèi):?jiǎn)沃底⒔?、?biāo)記注解和完整注解。注解只是作為標(biāo)識(shí)存在,一般不會(huì)直

28、接影響到程序的語(yǔ)義,通過(guò)反射機(jī)制我們可以訪問(wèn)到這些元數(shù)據(jù),元數(shù)據(jù)就是用來(lái)描述數(shù)據(jù)的數(shù)據(jù)。注解的存在級(jí)別一共有三種:RUNTIME,CLASS,SOURCE。RUNTIME表示運(yùn)行時(shí)存在,CLASS表示能作用于class文件,SOURCE表示只存在源代碼中。程序員可在編譯時(shí)選擇代碼的存在級(jí)別。 [11]</p><p><b>  基本作用</b></p><p>  

29、雖然對(duì)于注解的作用還沒(méi)有明確的定義,但是大致可以分為三種:</p><p>  編寫(xiě)文檔:檢查代碼中存在的標(biāo)識(shí)注解來(lái)生成文檔。</p><p>  代碼分析:以代碼中標(biāo)識(shí)的注解對(duì)代碼進(jìn)行分析。</p><p>  編譯檢查:檢查標(biāo)識(shí)的注解使編譯器能執(zhí)行基礎(chǔ)的編譯檢查。[12]</p><p><b>  基本的內(nèi)置注解</b&

30、gt;</p><p>  @Override:只能用在方法上,用來(lái)申明該方法是改寫(xiě)父類(lèi)的。</p><p>  @Deprecated:對(duì)于棄用的方法添加的注解。當(dāng)程序員調(diào)用這些方法時(shí), 在編譯時(shí)將會(huì)顯示提示信息。該注解可添加在程序的所有元素上。 </p><p>  @SuperressWarnings:暫時(shí)關(guān)閉警告信息。[13]</p>&

31、lt;p>  基于注解的IoC和AOP的實(shí)現(xiàn)</p><p>  就IoC而言,主要實(shí)現(xiàn)是靠設(shè)計(jì)模式中的工廠模式,工廠模式負(fù)責(zé)將大量具有Component注解的類(lèi)進(jìn)行實(shí)例化,而不必事先知道每次是要實(shí)例化哪一個(gè)類(lèi)。換句話說(shuō),工廠模式對(duì)于具體的new的細(xì)節(jié)都進(jìn)行了隱藏和封裝。</p><p>  對(duì)于工廠模式的優(yōu)點(diǎn)主要分為下列四點(diǎn):</p><p>  代碼結(jié)構(gòu)清

32、晰,具有良好的封裝性。對(duì)于對(duì)象的創(chuàng)建不是無(wú)條件的。假設(shè)一個(gè)調(diào)用者需要一個(gè)具體的產(chǎn)品,調(diào)用者并不需要知道產(chǎn)品具體是如何被生產(chǎn)的。對(duì)于他而言只需要知道產(chǎn)品類(lèi)名或者產(chǎn)品約束字符串就可以了,從而降低模塊耦合度。</p><p>  優(yōu)秀的可擴(kuò)展性。如果具體需求需要增加產(chǎn)品,不必具體對(duì)產(chǎn)品類(lèi)進(jìn)行修改,只需適當(dāng)修改工廠類(lèi)或者再增加一個(gè)工廠就可以了。</p><p>  屏蔽產(chǎn)品類(lèi)。對(duì)于具體產(chǎn)品是如何生

33、產(chǎn)的,調(diào)用者并不用關(guān)心,他的關(guān)注點(diǎn)主要在于產(chǎn)品的接口。如果產(chǎn)品接口不發(fā)生變化,那么系統(tǒng)上層的模塊也不會(huì)發(fā)生改變。具體的產(chǎn)品的實(shí)例化主要由工廠類(lèi)管理,對(duì)于不同的產(chǎn)品對(duì)象的生產(chǎn)應(yīng)取決于不同的工廠類(lèi)。</p><p>  關(guān)于工廠方法的經(jīng)典應(yīng)用就是解耦合了。處于較高層的模塊只需知道實(shí)現(xiàn)類(lèi)的接口,具體實(shí)現(xiàn)類(lèi)無(wú)需關(guān)心。對(duì)于工廠方法,它也遵循迪米特和依賴(lài)倒置法則,僅僅依賴(lài)實(shí)現(xiàn)類(lèi)的接口;除此之外,工廠方法也遵循里氏替換原則,子

34、類(lèi)可以隨時(shí)隨地替換父類(lèi)。[14]</p><p>  而對(duì)于AOP來(lái)說(shuō),在掃描系統(tǒng)組件時(shí),如果該組件存在Interception注解且已聲明需要攔截的方法。那么在調(diào)用存在Interception注解的類(lèi)的方法時(shí),如果該方法已被攔截,則該方法執(zhí)行前和執(zhí)行后會(huì)進(jìn)行相應(yīng)的操作。而實(shí)現(xiàn)AOP技術(shù)主要用到了代理模式。</p><p>  對(duì)于使用代理模式,只要有點(diǎn)體現(xiàn)在以下幾個(gè)方面:</p&g

35、t;<p>  職責(zé)清晰:具體的產(chǎn)品類(lèi)實(shí)現(xiàn)具體的業(yè)務(wù),不必去在意非自身所要實(shí)現(xiàn)的業(yè)務(wù)。如需其他業(yè)務(wù)可通過(guò)后期代理完成附加,此種做法的好處是代碼簡(jiǎn)潔清晰。</p><p>  高擴(kuò)展性:對(duì)于產(chǎn)品類(lèi)可能需求不同,但是只要是實(shí)現(xiàn)了其接口的,可通過(guò)代理手段代理各種產(chǎn)品類(lèi),而代理類(lèi)卻不用做任何修改。</p><p>  智能化:代理對(duì)象可在運(yùn)行時(shí)才去調(diào)用具體的代理類(lèi),換言之就是代理類(lèi)可

36、以在運(yùn)行時(shí)才確定代理對(duì)象。[15]</p><p><b>  注解的編寫(xiě)</b></p><p>  在本文中,主要用到的注解有@Component,@Property,@Aspect,@Interception。@Component注解主要說(shuō)明該類(lèi)是一個(gè)組件,用于在初始化容器時(shí)將其實(shí)例創(chuàng)建放入一個(gè)Map中;@Property注解主要說(shuō)明該類(lèi)是組件類(lèi)的屬性,在運(yùn)行時(shí)

37、將注入屬性,以便調(diào)用該類(lèi)的方法;@Aspect注解主要用于說(shuō)明該類(lèi)是一個(gè)切面類(lèi),用來(lái)執(zhí)行在攔截方法執(zhí)行過(guò)程中要處理的操作;@Interception注解用于說(shuō)明該類(lèi)中的方法需要被攔截,可指定要攔截的方法,攔截下來(lái)的方法將先進(jìn)行其他操作,如事務(wù)處理。具體注解的代碼如下:</p><p>  @Component注解:</p><p>  public @interface Component

38、 {</p><p>  //組件在HashTable中的名字,當(dāng)為空時(shí)默認(rèn)為組件類(lèi)名的小寫(xiě)</p><p>  public String name() default "";</p><p>  //組件是否存在單例,默認(rèn)為存在</p><p>  public boolean isSingleton() defaul

39、t true;</p><p><b>  }</b></p><p>  @Property注解:</p><p>  public @interface Property {</p><p>  //需要注入的屬性注入的對(duì)象的名稱(chēng),默認(rèn)為空時(shí)則直接獲取組件中屬性的名稱(chēng)</p><p>  pu

40、blic String ref() default "";</p><p><b>  }</b></p><p>  @Aspect注解:</p><p>  public @interface Aspect {</p><p><b>  //切面類(lèi)的名稱(chēng)</b></p

41、><p>  public String name() default "";</p><p><b>  }</b></p><p>  @Interception注解:</p><p>  public @interface Interception {</p><p><

42、;b>  //攔截的方法</b></p><p>  public String[]methods();</p><p><b>  }</b></p><p>  IoC實(shí)現(xiàn)(對(duì)象工廠)</p><p>  首先,在工廠初始化的時(shí)候會(huì)創(chuàng)建組件的對(duì)象,而對(duì)于組件類(lèi)的存放放在對(duì)應(yīng)的包中,對(duì)于讀取的包及包的

43、掃描則配置在XML中。讀取XML獲取包名及子包名代碼如下:</p><p>  String packageInfo="";</p><p>  URL url=XMLParse.class.getResource("");</p><p>  File file=new File(url.getPath()+xmlName

44、);</p><p>  DocumentBuilder builder=null;</p><p><b>  try {</b></p><p>  builder=DocumentBuilderFactory.newInstance().newDocumentBuilder();</p><p>  Documen

45、t doc=builder.parse(file);</p><p>  Element ele=doc.getDocumentElement();</p><p>  NodeList nls=ele.getChildNodes();</p><p>  Element ce=null;</p><p>  for (int i = 0;

46、i < nls.getLength(); i++) {</p><p>  Node n=nls.item(i);</p><p>  if(n.getNodeType()==Node.ELEMENT_NODE){</p><p>  if(n.getNodeName().equals("component-package")){</

47、p><p>  ce=(Element)n;</p><p><b>  break;</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p>

48、<p>  packageInfo=ce.getTextContent();</p><p>  } catch (Exception e) {</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p>  其次通過(guò)包名,獲取包中的所有類(lèi),而類(lèi)的存放

49、是以文件形式存在,則需進(jìn)行文件的掃描。文件掃描代碼如下:</p><p>  public void findAndAddClassesInPackageByFile(String packageName,</p><p>  String physicsPath, final boolean recursive, Set<Class<?>> classes) {&

50、lt;/p><p>  //獲取此包的目錄建立一個(gè)file</p><p>  File dir=new File(physicsPath);</p><p>  //如果不存在或者也不是一個(gè)目錄就直接返回</p><p>  if(!dir.exists()||!dir.isDirectory()){</p><p>&

51、lt;b>  return;</b></p><p><b>  }</b></p><p>  //如果存在就獲取包下的所有文件及目錄</p><p>  File[] dirFiles=dir.listFiles(new FileFilter() {</p><p><b>  @Over

52、ride</b></p><p>  public boolean accept(File file) {</p><p>  //如果可以循環(huán)(即包含子目錄)或是以.class結(jié)尾的文件(即編譯好的java文件)</p><p>  return (recursive&&file.isDirectory())||(file.getNam

53、e().endsWith(".class"));</p><p><b>  }</b></p><p><b>  });</b></p><p><b>  //循環(huán)所有文件</b></p><p>  for (File file : dirFiles

54、) {</p><p>  //如果是目錄則繼續(xù)掃描</p><p>  if(file.isDirectory()){</p><p>  findAndAddClassesInPackageByFile(packageName+"."+file.getName(), file.getAbsolutePath(), recursive, cla

55、sses);</p><p><b>  }else{</b></p><p>  //如果是java類(lèi)文件去掉后面的.class只留下類(lèi)名</p><p>  String className=file.getName().substring(0,file.getName().length()-6);</p><p>

56、  //System.out.println(className);</p><p><b>  try {</b></p><p><b>  //添加到集合中</b></p><p>  //System.out.println(packageName+'.'+className);</p>

57、<p>  classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName+'.'+className));</p><p>  } catch (Exception e) {</p><p>  e.printStackTrace();</p>&

58、lt;p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  獲取包中所有類(lèi)的代碼如下:</p><p>  pu

59、blic Set<Class<?>>getClasses(String packages){</p><p>  //存放包中的class</p><p>  Set<Class<?>>classes=new LinkedHashSet<Class<?>>();</p><p><b>

60、;  //是否迭代循環(huán)</b></p><p>  boolean recursive=true;</p><p>  //將包名從以"."隔開(kāi)換成以"/"隔開(kāi)</p><p>  String packageName=packages;</p><p>  String packageTo

61、Dir=packageName.replace(".", "/");</p><p>  //System.out.println(packageToDir);</p><p>  //定義一個(gè)枚舉的集合循環(huán)處理該目錄下的所有東西</p><p>  Enumeration<URL> dirs;</p>

62、<p><b>  try {</b></p><p>  dirs=Thread.currentThread().getContextClassLoader().getResources(packageToDir);</p><p><b>  //循環(huán)迭代</b></p><p>  while(dirs

63、.hasMoreElements()){</p><p><b>  //獲取下一個(gè)元素</b></p><p>  URL url=dirs.nextElement();</p><p><b>  //獲取協(xié)議名</b></p><p>  String protocal=url.getProt

64、ocol();</p><p>  //如果是文件形式保存在服務(wù)器上</p><p>  if("file".equals(protocal)){</p><p>  //System.err.println("file類(lèi)型的掃描");</p><p>  //獲取包的物理路勁</p>&

65、lt;p>  String physicsPath=URLDecoder.decode(url.getFile(), "utf-8");</p><p>  //sSystem.out.println(physicsPath);</p><p>  //以文件方式掃描整個(gè)包下的文件并添加到集合中</p><p>  findAndAddCl

66、assesInPackageByFile(packageName,physicsPath,recursive,classes);</p><p>  }else if("jar".equals(protocal)){</p><p>  //如果是jar文件,則定義一個(gè)jarFile</p><p>  JarFile jar;</p>

67、;<p><b>  try {</b></p><p><b>  //獲取jar</b></p><p>  jar=((JarURLConnection)url.openConnection()).getJarFile();</p><p>  //從此jar包中獲取一個(gè)枚舉類(lèi)</p>&

68、lt;p>  Enumeration<JarEntry>entries=jar.entries();</p><p>  //同樣進(jìn)行循環(huán)迭代</p><p>  while(entries.hasMoreElements()){</p><p>  //獲取jar里的一個(gè)實(shí)體,可以是目錄和一些jar包里的其他文件,如META-INF等文件<

69、/p><p>  JarEntry entry=entries.nextElement();</p><p>  String name=entry.getName();</p><p>  //如果以"/"開(kāi)頭</p><p>  if(name.charAt(0)=='/'){</p><

70、;p>  //獲取"/"后的字符串</p><p>  name=name.substring(1);</p><p><b>  }</b></p><p>  //如果前半部分與定義的包名相同</p><p>  if(name.startsWith(packageToDir)){</

71、p><p>  //若以"/"結(jié)尾是一個(gè)包</p><p>  int index=name.lastIndexOf("/");</p><p>  if(index!=-1){</p><p>  //獲取包名且把"/"替換成"."</p><p

72、>  packageName=name.substring(0,index).replace("/", ".");</p><p><b>  }</b></p><p>  //若可迭代下去且是一個(gè)包</p><p>  if((index!=-1)||recursive){</p>

73、<p>  if(name.endsWith(".class")&&!entry.isDirectory()){</p><p>  //去掉".class"獲取正真的類(lèi)名</p><p>  String className=name.substring(packageName.length()+1,name.lengt

74、h()-6);</p><p><b>  try {</b></p><p>  //添加到classes中</p><p>  classes.add(Class.forName(packageName+"."+className));</p><p>  } catch (Exception e

75、) {</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b>&l

76、t;/p><p><b>  } </b></p><p>  }catch (Exception e) {</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p><b>  }</b><

77、/p><p><b>  }</b></p><p>  } catch (Exception e) {</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p>  return classes;</p>

78、<p><b>  }</b></p><p>  接著就是對(duì)工廠的初始化。具體代碼如下:</p><p>  public void init() {</p><p>  //獲取配置文件中的包信息</p><p>  String packageInfo=XMLParse.getInstance().ge

79、tPackage();</p><p>  //System.out.println(packageInfo);</p><p>  //獲取包下的所有class</p><p>  Set<Class<?>>classes=getClasses(packageInfo);</p><p>  //System.out

80、.println(classes.size());</p><p>  for (Class<?> cls : classes) {</p><p>  //判斷是否存在Component注解</p><p>  if(cls.isAnnotationPresent(Component.class)){</p><p><b

81、>  //獲取注解對(duì)象</b></p><p>  Component component=cls.getAnnotation(Component.class);</p><p>  //獲取注解name的屬性值</p><p>  String comName=component.name();</p><p><b

82、>  try {</b></p><p>  //判斷注解comName是否為空</p><p>  if(comName.equals("")){</p><p>  //如果為空將comName設(shè)置為類(lèi)名的小寫(xiě)</p><p>  comName=cls.getSimpleName();</p&

83、gt;<p>  comName=comName.substring(0,1).toLowerCase()+comName.substring(1);</p><p>  //System.out.println(comName);</p><p><b>  }</b></p><p>  //最終將處理后或未處理的類(lèi)名對(duì)應(yīng)的實(shí)

84、例存入cms中</p><p>  cms.put(comName, cls.newInstance());</p><p>  } catch (Exception e) {</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p>&

85、lt;b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  接下來(lái)則是在程序運(yùn)行過(guò)程中,對(duì)存在@Property注解的屬性進(jìn)行屬性注入,獲取其對(duì)應(yīng)的實(shí)例對(duì)象。具體代碼如下:</p><p>  public <

86、T> T getObject(String name,Class<T> cz){</p><p>  T target=(T)cms.get(name);</p><p>  //獲取組件時(shí)首先要判斷該組件是否存在</p><p>  if(target==null){</p><p>  throw new Runtime

87、Exception("對(duì)象不存在");</p><p><b>  }</b></p><p>  //如果對(duì)象存在,則要判斷對(duì)象是否需要注入屬性,如果需要注入屬性,則先注入屬性在返回對(duì)象</p><p>  Field []fields=target.getClass().getDeclaredFields();</

88、p><p>  for (Field field : fields) {</p><p>  //判斷該屬性是否存在Property注解</p><p>  if(field.isAnnotationPresent(Property.class)){</p><p><b>  //獲取屬性名</b></p>

89、<p>  String fieldName=field.getName();</p><p>  Property pro=(Property)field.getAnnotation(Property.class);</p><p>  String ref=pro.ref();</p><p>  //判斷ref是否為空</p><

90、p>  if(ref.equals("")){</p><p>  ref=fieldName;</p><p><b>  }</b></p><p>  //獲取set方法的名稱(chēng)</p><p>  String methodName="set"+fieldName.su

91、bstring(0,1).toUpperCase()+fieldName.substring(1);</p><p><b>  try {</b></p><p>  Method m=cz.getMethod(methodName, field.getType());</p><p>  m.invoke(target, this.getO

92、bject(ref, field.getType()));</p><p>  } catch (Exception e) {</p><p>  e.printStackTrace();</p><p><b>  }</b></p><p>  //target=this.getObject(fieldName, c

93、z);</p><p><b>  }</b></p><p><b>  }</b></p><p>  if(target.getClass().isAnnotationPresent(Interception.class)){</p><p>  Interception inter=targ

94、et.getClass().getAnnotation(Interception.class);</p><p><b>  //攔截的方法</b></p><p>  String methods[]=inter.methods();</p><p>  SpringInterceptor mi=null;</p><p&

95、gt;<b>  try {</b></p><p>  mi=(SpringInterceptor)Class.forName(interceptionName).newInstance();</p><p>  mi.setMethodsName(methods);</p><p>  mi.setTarget(target.getClas

96、s().newInstance());</p><p>  } catch(ClassNotFoundException e){</p><p>  e.printStackTrace();</p><p>  }catch (InstantiationException e) {</p><p>  // TODO Auto-generat

97、ed catch block</p><p>  e.printStackTrace();</p><p>  } catch (IllegalAccessException e) {</p><p>  // TODO Auto-generated catch block</p><p>  e.printStackTrace();<

98、/p><p><b>  }</b></p><p>  return (T)mi.getInstance();</p><p><b>  }</b></p><p>  return target;</p><p><b>  }</b></p&g

99、t;<p>  在屬性注入的同時(shí)會(huì)判斷該屬性是否存在攔截器以及要攔截的方法。接下來(lái)則是利用AOP實(shí)現(xiàn)攔截器功能。</p><p>  AOP實(shí)現(xiàn)(攔截器)</p><p>  對(duì)于攔截器,其實(shí)就是代理模式的具體實(shí)現(xiàn),首先需實(shí)現(xiàn)InvocationHandler接口,該接口是代理實(shí)例的調(diào)用處理程序?qū)崿F(xiàn)的接口。對(duì)于各個(gè)代理實(shí)例都被聯(lián)接了具體的處理程序代碼。在代理實(shí)例調(diào)用處理程序時(shí)

100、,將對(duì)該程序方法編碼設(shè)置且將其指派到它的invoke方法。 </p><p>  以下是實(shí)現(xiàn)InvocationHandler的抽象類(lèi),該類(lèi)需要一個(gè)目標(biāo)對(duì)象及該目標(biāo)對(duì)象需要攔截的方法。具體代碼如下:</p><p>  public abstract class SpringInterceptor implements InvocationHandler {</p><

101、p><b>  //目標(biāo)對(duì)象</b></p><p>  private Object target;</p><p><b>  //所要攔截的方法</b></p><p>  private String[] methodsName;</p><p>  public Object get

102、Instance(){</p><p>  Object obj=Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);</p><p>  return obj;</p><p><b>  }</b&g

103、t;</p><p>  public void setTarget(Object target){</p><p>  this.target=target;</p><p><b>  }</b></p><p>  public void setMethodsName(String[] methodsName){&

104、lt;/p><p>  this.methodsName=methodsName;</p><p><b>  }</b></p><p><b>  @Override</b></p><p>  public Object invoke(Object proxy, Method method, Ob

105、ject[] args)</p><p>  throws Throwable {</p><p>  for (String name : methodsName) {</p><p>  if(name.equals(method.getName())){</p><p>  return interceptor(target,metho

106、d,args);</p><p><b>  }</b></p><p><b>  }</b></p><p>  return method.invoke(target, args);</p><p><b>  }</b></p><p><

107、b>  /**</b></p><p><b>  * </b></p><p>  * @param target 攔截類(lèi)的對(duì)象</p><p>  * @param method 攔截的方法</p><p>  * @param args 方法的參數(shù)</p><p>  *

108、@return 返回值</p><p>  * @throws IllegalArgumentException</p><p>  * @throws IllegalAccessException</p><p>  * @throws InvocationTargetException</p><p><b>  */</

109、b></p><p>  public abstract Object interceptor(Object target, Method method, Object[] args)throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;</p><p><b>

110、;  }</b></p><p>  接下來(lái)則是編寫(xiě)具體實(shí)現(xiàn)攔截功能的實(shí)現(xiàn)類(lèi)。具體代碼如下:</p><p>  public class MyInterception extends SpringInterceptor {</p><p><b>  @Override</b></p><p>  publ

111、ic Object interceptor(Object target, Method method, Object[] args)</p><p>  throws IllegalArgumentException, IllegalAccessException,</p><p>  InvocationTargetException {</p><p>  Ob

112、ject result=null;</p><p>  System.out.println("開(kāi)啟事務(wù)");</p><p>  result=method.invoke(target, args);</p><p>  System.out.println("提交事務(wù)");</p><p>  re

113、turn result;</p><p><b>  }</b></p><p><b>  }</b></p><p>  至此,基本實(shí)現(xiàn)了攔截器功能。對(duì)于AOP編程,能實(shí)現(xiàn)的功能主要有事務(wù)處理、性能監(jiān)測(cè)、日志記錄、安全控制等,在這里只是象征性的輸出語(yǔ)句。</p><p>  IoC和AOP實(shí)現(xiàn)流

114、程圖</p><p>  根據(jù)IoC和AOP的描述以及實(shí)現(xiàn)程序,繪制了實(shí)現(xiàn)的基本流程圖,如圖3.1和圖3.2所示:</p><p>  基于注解的IoC和AOP的框架在WEB中的應(yīng)用</p><p>  下面是該框架在WEB中的應(yīng)用,主要為了驗(yàn)證IoC和AOP,所以只是實(shí)現(xiàn)了簡(jiǎn)單的增刪改查,而沒(méi)有過(guò)多是去追求系統(tǒng)的其他功能。前臺(tái)顯示頁(yè)面利用AJAX異步請(qǐng)求數(shù)據(jù),當(dāng)訪

115、問(wèn)主頁(yè)就會(huì)顯示數(shù)據(jù),對(duì)于顯示的方法并沒(méi)有進(jìn)行攔截。提供基本的增刪改功能,當(dāng)點(diǎn)擊相應(yīng)功能時(shí)會(huì)提交給servlet進(jìn)行處理,servlet中將創(chuàng)建service層的對(duì)象,而對(duì)象的創(chuàng)建利用框架中的獲取對(duì)象方法,而不是直接new出來(lái),實(shí)現(xiàn)了層與層之間的松耦合。在service層將申明dao層的屬性,配有setDao方法獲取屬性對(duì)象。而在dao層中將實(shí)現(xiàn)方法的攔截,攔截的方法主要就是增刪改,對(duì)于攔截的方法會(huì)進(jìn)行相應(yīng)的處理,而在這只是象征性的輸出語(yǔ)

116、句。下面是WEB的具體實(shí)現(xiàn)。</p><p>  表4.1 用戶信息表</p><p><b>  用戶顯示</b></p><p>  當(dāng)客戶端訪問(wèn)主界面時(shí),主界面中利用AJAX異步請(qǐng)求servlet,將傳過(guò)去一個(gè)op,也就是請(qǐng)求的操作。servlet根據(jù)請(qǐng)求的op判斷該執(zhí)行什么操作,然后調(diào)用相應(yīng)的方法。在這里則是進(jìn)行查詢操作。在servle

117、t中將使用框架中的對(duì)象工廠獲取service層,也就是業(yè)務(wù)層的對(duì)象,所以servlet將調(diào)用service層的查詢方法。而在service層中存在dao層(數(shù)據(jù)訪問(wèn)層)的屬性,要想獲取dao層的對(duì)象,首先需對(duì)dao屬性進(jìn)行set處理,這樣在對(duì)象工廠初始化的時(shí)候凡是有@Property注解的將通過(guò)set方式注入其對(duì)象。當(dāng)然也會(huì)判斷該屬性對(duì)應(yīng)的類(lèi)是否需要方法攔截。在該web顯示中只對(duì)修改、刪除和更新用戶的方法進(jìn)行了攔截,對(duì)于其他方法并沒(méi)有進(jìn)

118、行攔截。用戶顯示如下圖所示:</p><p>  圖4.2 用戶信息顯示</p><p>  查詢用戶的servlet代碼如下所示:</p><p><b>  //查詢相關(guān)用戶</b></p><p>  List<User>users=userService.queryUser();</p>

119、<p>  ObjectMapper mapper=new ObjectMapper();</p><p>  //將其轉(zhuǎn)換成json數(shù)據(jù)</p><p>  String json=mapper.writeValueAsString(users);</p><p>  response.setCharacterEncoding("utf-8&

120、quot;);</p><p>  PrintWriter pw=response.getWriter();</p><p>  pw.write(json);</p><p>  pw.flush();</p><p>  pw.close();</p><p><b>  用戶的增刪改</b>

121、</p><p>  對(duì)于用戶的增刪改操作,具體實(shí)現(xiàn)方法不同,但大致的操作過(guò)程和查詢用戶類(lèi)似,在這里就不再贅述。唯一有區(qū)別的就是,對(duì)于用戶的增刪改方法進(jìn)行了方法攔截,即在dao層中存在@Intecerption注解,并指明了攔截的方法有“saveUser”,“delUser”和“updateUser”。對(duì)于攔截的方法采用AOP編程思想,將調(diào)用具有@Aspect注解的類(lèi),在方法執(zhí)行過(guò)程中執(zhí)行該類(lèi)相應(yīng)的方法。但是在本

122、web實(shí)現(xiàn)中也只是象征性的輸出語(yǔ)句。具體增加修改用戶的頁(yè)面和進(jìn)行攔截的結(jié)果如下所示:</p><p><b>  圖4.3 增加用戶</b></p><p><b>  圖4.4 修改用戶</b></p><p>  增刪改底層公共代碼如下:</p><p><b>  /**</b

123、></p><p>  * 底層增刪改公共類(lèi)</p><p>  * @param sql 執(zhí)行的sql語(yǔ)句</p><p>  * @param o sql語(yǔ)句占位參數(shù)</p><p><b>  */</b></p><p>  public void execute(String sq

124、l,Object[] o){</p><p>  Connection con=null;</p><p>  PreparedStatement ps=null;</p><p><b>  try {</b></p><p>  con=getCon();</p><p>  ps=con.p

125、repareStatement(sql);</p><p>  for (int i = 0; i < o.length; i++) {</p><p>  ps.setObject(i+1, o[i]);</p><p><b>  }</b></p><p>  ps.executeUpdate();</

126、p><p>  } catch (Exception e) {</p><p>  e.printStackTrace();</p><p><b>  }finally{</b></p><p>  closeAll(null, ps, con);</p><p><b>  }</

溫馨提示

  • 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ù)僅提供信息存儲(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)論