成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java反射-動(dòng)態(tài)代理

Acceml / 803人閱讀

摘要:動(dòng)態(tài)代理有多種不同的用途,例如,數(shù)據(jù)庫(kù)連接和事務(wù)管理用于單元測(cè)試的動(dòng)態(tài)模擬對(duì)象其他類似的方法攔截。調(diào)用序列和下面的流程類似單元測(cè)試動(dòng)態(tài)對(duì)象模擬利用動(dòng)態(tài)代理實(shí)現(xiàn)單元測(cè)試的動(dòng)態(tài)存根代理和代理。框架把包裝成動(dòng)態(tài)代理。

使用反射可以在運(yùn)行時(shí)動(dòng)態(tài)實(shí)現(xiàn)接口。這可以使用類java.lang.reflect.Proxy。這個(gè)類的名稱是我將這些動(dòng)態(tài)接口實(shí)現(xiàn)稱之為動(dòng)態(tài)代理的原因。動(dòng)態(tài)代理有多種不同的用途,例如,數(shù)據(jù)庫(kù)連接和事務(wù)管理、用于單元測(cè)試的動(dòng)態(tài)模擬對(duì)象、其他類似AOP的方法攔截。

創(chuàng)建代理

可以使用Proxy.newProxyInstance() 方法創(chuàng)建動(dòng)態(tài)代理。newProxyInstance() 方法有3個(gè)參數(shù):

"load"動(dòng)態(tài)代理類的ClassLoader

需要實(shí)現(xiàn)的接口數(shù)組

接收所有方法轉(zhuǎn)發(fā)的InvocationHandler

示例如下:

InvocationHandler handler = new MyInvocationHandler();
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
                            MyInterface.class.getClassLoader(),
                            new Class[] { MyInterface.class },
                            handler);

運(yùn)行代碼后,變量proxy包含一個(gè)MyInterface接口的動(dòng)態(tài)實(shí)現(xiàn)。所有對(duì)代理對(duì)象的調(diào)用將被轉(zhuǎn)發(fā)到InvocationHandler接口的實(shí)現(xiàn)handler。InvocationHandler會(huì)在下一節(jié)介紹。

調(diào)用處理程序

前文已經(jīng)提到,必須傳一個(gè)InvocationHandler實(shí)現(xiàn)給Proxy.newProxyInstance()方法。所有動(dòng)態(tài)代理調(diào)用都會(huì)傳給InvocationHandler實(shí)現(xiàn)。InvocationHandler接口代碼如下:

public interface InvocationHandler{
  Object invoke(Object proxy, Method method, Object[] args)
         throws Throwable;
}

示例實(shí)現(xiàn)如下:

public class MyInvocationHandler implements InvocationHandler{

  public Object invoke(Object proxy, Method method, Object[] args)
  throws Throwable {
    //do something "dynamic"
  }
}

傳給invoke()方法的proxy參數(shù)是實(shí)現(xiàn)了對(duì)應(yīng)接口的動(dòng)態(tài)代理對(duì)象。通常情況下,你不需要這個(gè)對(duì)象。
傳給invoke()方法的Method對(duì)象代表調(diào)用動(dòng)態(tài)代理實(shí)現(xiàn)的接口的方法。從Method對(duì)象可以獲得方法名稱、參數(shù)類型、返回值類型等。Methods 節(jié)有關(guān)于方法更詳細(xì)的描述。
Object[] args數(shù)組包含動(dòng)態(tài)代理對(duì)象被調(diào)用的方法需要使用的參數(shù)。注意:基本類型(int、lang等)在動(dòng)態(tài)代理中需要使用它們的包裝類型(Integer、Long等)。

已知用例

已知?jiǎng)討B(tài)代理至少用于以下目的:

數(shù)據(jù)庫(kù)連接和事務(wù)管理

用于單元測(cè)試的動(dòng)態(tài)對(duì)象模擬

適配DI容器以自定義工廠接口

類AOP的方法攔截

數(shù)據(jù)庫(kù)連接與事務(wù)管理

Spring框架有一個(gè)事務(wù)代理,可以開(kāi)啟、提交/回滾事務(wù)。它是如何工作的,在文章Advanced Connection and Transaction Demarcation and Propagation中有詳細(xì)講解,所以這里只做簡(jiǎn)要介紹。調(diào)用序列和下面的流程類似:

web controller --> proxy.execute(...);
  proxy --> connection.setAutoCommit(false);
  proxy --> realAction.execute();
    realAction does database work
  proxy --> connection.commit();
單元測(cè)試動(dòng)態(tài)對(duì)象模擬

Butterfly Testing Tools 利用動(dòng)態(tài)代理實(shí)現(xiàn)單元測(cè)試的動(dòng)態(tài)存根、代理和代理。當(dāng)使用類B(真實(shí)接口)測(cè)試類A,可以傳一個(gè)B的模擬實(shí)現(xiàn)給A以代替真實(shí)的B。所有的對(duì)B的方法調(diào)用都會(huì)被記錄,也可以去設(shè)置B模擬對(duì)象的返回值。
此外,Butterfly Testing Tools允許您包裝真實(shí)B為模擬B,所以對(duì)模擬B方法的調(diào)用都會(huì)被記錄,并且可以轉(zhuǎn)發(fā)到真實(shí)B。所以,這可以用來(lái)檢測(cè)調(diào)用真實(shí)B的方法。例如,如果測(cè)試一個(gè)Dao,你可以包裝數(shù)據(jù)庫(kù)連接為一個(gè)模擬對(duì)象。Dao是不知道區(qū)別的,且Dao可以按常用方法讀寫(xiě)數(shù)據(jù),這是因?yàn)槟M對(duì)象轉(zhuǎn)發(fā)給了數(shù)據(jù)庫(kù)連接。但是,現(xiàn)在你也通過(guò)模擬對(duì)象檢查Dao連接的屬性,例如如果調(diào)用了connection.close()(或者沒(méi)有調(diào)用),如果你期望的話。這通常不可能從DAO的返回值來(lái)確定。

DI容器與自定義工廠的適配

依賴注入容器Butterfly Container有一個(gè)非常強(qiáng)大的特性,它允許你把整個(gè)容器注入到它創(chuàng)建的bean中。但是,你可能不希望在容器接口上有依賴,容器能自動(dòng)適配你自定義的工廠接口。你只需要接口,不需要實(shí)現(xiàn)。因此,工廠接口和你的類可能像這樣:

public interface IMyFactory {
  Bean   bean1();
  Person person();
  ...
}
public class MyAction{

  protected IMyFactory myFactory= null;

  public MyAction(IMyFactory factory){
    this.myFactory = factory;
  }

  public void execute(){
    Bean bean = this.myFactory.bean();
    Person person = this.myFactory.person();
  }

}

當(dāng)MyAction類調(diào)用容器通過(guò)構(gòu)造函數(shù)注入的IMyFactory實(shí)例的方法時(shí),方法調(diào)用被轉(zhuǎn)化為調(diào)用IContainer.instance()的方法,這是從容器的實(shí)例獲取的方法。因此,一個(gè)對(duì)象可以把Butterfly Container作為一個(gè)運(yùn)行時(shí)工廠使用,而不僅僅是在創(chuàng)建時(shí)注入。并且,這對(duì)Butterfly Container 接口沒(méi)有特殊依賴。

類AOP的方法攔截

Spring框架可以攔截所有對(duì)bean的方法調(diào)用,假如bean實(shí)現(xiàn)了某些接口。Spring框架把bean包裝成動(dòng)態(tài)代理。所有bean調(diào)用都被動(dòng)態(tài)代理截獲。代理在把調(diào)用請(qǐng)求委派給bean之前或之后可以決定去調(diào)用其他對(duì)象的其他方法。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71693.html

相關(guān)文章

  • Java 動(dòng)態(tài)反射代理

    摘要:靜態(tài)方法生成動(dòng)態(tài)代理類同樣需要通過(guò)類裝載器來(lái)進(jìn)行裝載才能使用,它與普通類的唯一區(qū)別就是其字節(jié)碼是由在運(yùn)行時(shí)動(dòng)態(tài)生成的而非預(yù)存在于任何一個(gè)文件中。 代理:設(shè)計(jì)模式 代理是一種常用的設(shè)計(jì)模式,其目的就是為其他對(duì)象提供一個(gè)代理以控制對(duì)某個(gè)對(duì)象的訪問(wèn)。代理類負(fù)責(zé)為委托類預(yù)處理消息,過(guò)濾消息并轉(zhuǎn)發(fā)消息,以及進(jìn)行消息被委托類執(zhí)行后的后續(xù)處理。showImg(https://segmentfault...

    Thanatos 評(píng)論0 收藏0
  • MyBatis初步

    摘要:本章主要介紹的是的基礎(chǔ)應(yīng)用和源碼涉及的相關(guān)等,主要包含的內(nèi)容有的簡(jiǎn)介反射動(dòng)態(tài)代理包含代理和代理使用和代碼生成器等。組件生命周期,如圖測(cè)試代碼生成器代碼生成器,又稱逆向工程。 本章主要介紹的是MyBatis的基礎(chǔ)應(yīng)用和源碼涉及的相關(guān)等,主要包含的內(nèi)容有MyBatis的簡(jiǎn)介、反射、動(dòng)態(tài)代理(包含JDK代理和cglib代理)、MyBatis使用和代碼生成器等。 1.1 MyBatis簡(jiǎn)介 M...

    MASAILA 評(píng)論0 收藏0
  • Java反射學(xué)習(xí)小記

    摘要:反射使用類對(duì)象提供的基本元數(shù)據(jù),能從類對(duì)象中找出方法或字段的名稱,然后獲取表示方法或字段的對(duì)象。常見(jiàn)的反射手段有反射和反射。以之前的反射為例其中指定了方法的返回類型,其實(shí)不止如此。 Java反射機(jī)制主要提供了以下功能: 在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象 在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法 在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法 生成動(dòng)態(tài)代理 很多框架...

    frank_fun 評(píng)論0 收藏0
  • Java高級(jí)程序員必備:反射、動(dòng)態(tài)代理

    摘要:相比硬編碼,反射要復(fù)雜的多,但其給我們帶來(lái)了更大的靈活性。實(shí)際上構(gòu)造函數(shù)也是類的靜態(tài)方法,因此使用關(guān)鍵字創(chuàng)建類的新對(duì)象也會(huì)被當(dāng)做對(duì)類的靜態(tài)引用,從而觸發(fā)類加載器對(duì)類的加載?;A(chǔ)基礎(chǔ)主要是為反射提供通用特性的接口或基類。 1. Java類型系統(tǒng) 獲取Java類型系統(tǒng),主要有兩個(gè)方式:一種是傳統(tǒng)的RTTI(Run-Time Type Identification),它假定我們?cè)诰幾g時(shí)已經(jīng)知...

    church 評(píng)論0 收藏0
  • Java編程思想》筆記14.類型信息

    摘要:接口與類型信息關(guān)鍵字的一種重要目標(biāo)就是允許程序員隔離構(gòu)件,進(jìn)而降低耦合性。如果你編寫(xiě)接口,那么就可以實(shí)現(xiàn)這一目標(biāo),但是通過(guò)類型信息,這種耦合性還是會(huì)傳播出去接口并非是對(duì)解耦的一種無(wú)懈可擊的保障。 點(diǎn)擊進(jìn)入我的博客 運(yùn)行時(shí)類型信息使得你可以在運(yùn)行時(shí)發(fā)現(xiàn)和使用類型信息,主要有兩種方式: 傳統(tǒng)的RTTI,它假定我們?cè)诰幾g時(shí)已經(jīng)知道了所有的類型; 反射機(jī)制,它允許我們?cè)谶\(yùn)行時(shí)發(fā)現(xiàn)和使用類的...

    Hwg 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<