2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩29頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、<p><b>  引言</b></p><p>  框架從某種意義上講是某種應(yīng)用的半成品,它是由一組組件所構(gòu)成。對于程序的重用性與所設(shè)計的系統(tǒng)的擴(kuò)展性以達(dá)到開發(fā)周期的縮減的目的與開發(fā)質(zhì)量的提高等目的,往往是框架一直追求并良好的實現(xiàn)了的。</p><p>  在軟件設(shè)計中,最終遵循的還是一個設(shè)計理念,就是“高內(nèi)聚,低耦合”??蚣芤话闶菍栴}分割成若干子問題進(jìn)

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

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

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

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

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

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

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

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

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

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

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

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

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

15、要進(jìn)行數(shù)據(jù)庫操作的類就必須得實現(xiàn)IBiz接口,業(yè)務(wù)邏輯類Biz實現(xiàn)這個接口IBiz。</p><p><b>  /*</b></p><p>  * 具體實現(xiàn)IBiz接口的類,重寫了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>  只有實現(xiàn)IBiz接口才能完成依賴注入。</p><p><b>  Set方法注入</b></p><p>  Set方法注入就是在需要屬性注入的類中定義一個Set方法,并設(shè)置注入元素為其參數(shù)。&l

18、t;/p><p>  假設(shè)業(yè)務(wù)層Biz依賴數(shù)據(jù)訪問層,且持有其屬性,需定義一個Set方法來接受數(shù)據(jù)訪問層的注入。</p><p>  public class Biz{</p><p>  //數(shù)據(jù)訪問層對象的引用</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ù)訪問層的方法及其他操作</p><p><b>  }</b></p><p><b>  構(gòu)造注入</b>

20、;</p><p>  構(gòu)造注入就是在需要屬性注入的類中提供一個有參構(gòu)造,其參數(shù)就是注入的元素。假設(shè)業(yè)務(wù)層Biz依賴數(shù)據(jù)訪問層,且持有其屬性,可通過一個構(gòu)造器來接受數(shù)據(jù)訪問層的注入。</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ù)訪問層的方法及其他操作</p><p><b>  }</b></p><p><b>  IoC圖解</b><

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

38、 {</p><p>  //組件在HashTable中的名字,當(dāng)為空時默認(rèn)為組件類名的小寫</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>  //需要注入的屬性注入的對象的名稱,默認(rèn)為空時則直接獲取組件中屬性的名稱</p><p>  pu

40、blic String ref() default "";</p><p><b>  }</b></p><p>  @Aspect注解:</p><p>  public @interface Aspect {</p><p><b>  //切面類的名稱</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實現(xiàn)(對象工廠)</p><p>  首先,在工廠初始化的時候會創(chuàng)建組件的對象,而對于組件類的存放放在對應(yīng)的包中,對于讀取的包及包的

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>  其次通過包名,獲取包中的所有類,而類的存放

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

50、lt;/p><p>  //獲取此包的目錄建立一個file</p><p>  File dir=new File(physicsPath);</p><p>  //如果不存在或者也不是一個目錄就直接返回</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類文件去掉后面的.class只留下類名</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>  獲取包中所有類的代碼如下:</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>  //將包名從以"."隔開換成以"/"隔開</p><p>  String packageName=packages;</p><p>  String packageTo

61、Dir=packageName.replace(".", "/");</p><p>  //System.out.println(packageToDir);</p><p>  //定義一個枚舉的集合循環(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>  //獲取下一個元素</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類型的掃描");</p><p>  //獲取包的物理路勁</p>&

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

66、assesInPackageByFile(packageName,physicsPath,recursive,classes);</p><p>  }else if("jar".equals(protocal)){</p><p>  //如果是jar文件,則定義一個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包中獲取一個枚舉類</p>&

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

69、/p><p>  JarEntry entry=entries.nextElement();</p><p>  String name=entry.getName();</p><p>  //如果以"/"開頭</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é)尾是一個包</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>  //若可迭代下去且是一個包</p><p>  if((index!=-1)||recursive){</p>

73、<p>  if(name.endsWith(".class")&&!entry.isDirectory()){</p><p>  //去掉".class"獲取正真的類名</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>  接著就是對工廠的初始化。具體代碼如下:</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、>  //獲取注解對象</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è)置為類名的小寫</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>  //最終將處理后或未處理的類名對應(yīng)的實

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>  接下來則是在程序運行過程中,對存在@Property注解的屬性進(jìn)行屬性注入,獲取其對應(yīng)的實例對象。具體代碼如下:</p><p>  public <

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

87、Exception("對象不存在");</p><p><b>  }</b></p><p>  //如果對象存在,則要判斷對象是否需要注入屬性,如果需要注入屬性,則先注入屬性在返回對象</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方法的名稱</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>  在屬性注入的同時會判斷該屬性是否存在攔截器以及要攔截的方法。接下來則是利用AOP實現(xiàn)攔截器功能。</p><p>  AOP實現(xiàn)(攔截器)</p><p>  對于攔截器,其實就是代理模式的具體實現(xiàn),首先需實現(xiàn)InvocationHandler接口,該接口是代理實例的調(diào)用處理程序?qū)崿F(xiàn)的接口。對于各個代理實例都被聯(lián)接了具體的處理程序代碼。在代理實例調(diào)用處理程序時

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

101、p><b>  //目標(biāo)對象</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 攔截類的對象</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>  接下來則是編寫具體實現(xiàn)攔截功能的實現(xiàn)類。具體代碼如下:</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("開啟事務(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>  至此,基本實現(xiàn)了攔截器功能。對于AOP編程,能實現(xiàn)的功能主要有事務(wù)處理、性能監(jiān)測、日志記錄、安全控制等,在這里只是象征性的輸出語句。</p><p>  IoC和AOP實現(xiàn)流

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

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

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

117、t中將使用框架中的對象工廠獲取service層,也就是業(yè)務(wù)層的對象,所以servlet將調(diào)用service層的查詢方法。而在service層中存在dao層(數(shù)據(jù)訪問層)的屬性,要想獲取dao層的對象,首先需對dao屬性進(jìn)行set處理,這樣在對象工廠初始化的時候凡是有@Property注解的將通過set方式注入其對象。當(dāng)然也會判斷該屬性對應(yīng)的類是否需要方法攔截。在該web顯示中只對修改、刪除和更新用戶的方法進(jìn)行了攔截,對于其他方法并沒有進(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>  對于用戶的增刪改操作,具體實現(xiàn)方法不同,但大致的操作過程和查詢用戶類似,在這里就不再贅述。唯一有區(qū)別的就是,對于用戶的增刪改方法進(jìn)行了方法攔截,即在dao層中存在@Intecerption注解,并指明了攔截的方法有“saveUser”,“delUser”和“updateUser”。對于攔截的方法采用AOP編程思想,將調(diào)用具有@Aspect注解的類,在方法執(zhí)行過程中執(zhí)行該類相應(yīng)的方法。但是在本

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

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

評論

0/150

提交評論