生活随笔
收集整理的這篇文章主要介紹了
代理模式与动态代理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介 的作用。這種情況原因很多,比如需要創建一個開銷很大的對象,或者被調用的對象在遠程主機上,或者目標對象的功能還不足以滿足需求。
代理模式一般涉及到的角色有–抽象角色 :聲明真實對象和代理對象的共同接口(可以看成租房子一件事)–代理角色 :代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當于對真實對象進行封裝(可以看成中介)–真實角色 :代理角色所代表的真實對象,是我們最終要引用的對象(可以看成房主)
靜態代理 真實對象已經存在,代理類能夠直接訪問到真實對象。
例如下面一個操作。一個接口Image,一個實現類BigImage,它的構造函數是一個比較耗時的操作,一個代理類ProxyImage,它持有對BigImage的引用,并進行了相對應的方法增強。
(1) 抽象角色
?
[java] view plaincopy
public?interface?Image?? {?? ????public?void?show();?? }?? (2) 真實角色
?
[java] view plaincopy
public?class?BigImage?implements?Image?? {?? ????public??BigImage()??? ????{?? ???????? ????????try?? ????????{?? ????????????Thread.sleep(3000);?? ????????}?? ????????catch?(InterruptedException?e)?? ????????{?? ???????????? ????????????e.printStackTrace();?? ????????}?? ????}?? ?? ????@Override?? ????public?void?show()?? ????{?? ????????System.out.println("BigImage?show?method");?? ?????????? ????}?? ?? }?? (3) 代理角色,定義了兩個方法對真實事件進行增強
?
[java] view plaincopy
public?class?ProxyImage?implements?Image?? {?? ????private?BigImage?bigImage; ?? ????@Override?? ????public?void?show()?? ????{?? ????????if(bigImage==null)?? ????????{?? ????????????bigImage=new?BigImage(); ????????}?? ????????preMethod();? ????????bigImage.show(); ????????postMethod(); ?? ????}?? ????private?void?preMethod()?? ????{?? ????????System.out.println("preMethod");?? ????}?? ????private?void?postMethod()?? ????{?? ????????System.out.println("postMethod");?? ????}?? ?? }?? (4) 測試代碼
?
[java] view plaincopy
public?static?void?main(String[]?args)?? ????{?? ????????System.out.println(System.currentTimeMillis()); ????????Image?image=new?ProxyImage();?? ????????System.out.println(System.currentTimeMillis()); ????????image.show();?? ????????System.out.println(System.currentTimeMillis());?? ????}?? 測試代碼很簡單,使用代理對象代替了真實對象,完成了同樣的事情,并且可以在原方法前后加入增強的方法。這里面分別顯示了初始化的時候,開始時間以及結束時間,可以看到耗時為0。那么這種代理到底有什么用呢?
(1)這種方式把比較耗時的操作推遲到了真正需要它的時候才創建,這樣能保證前面程序運行的流暢性,而且能夠減少BigImage在系統中存活時間,從宏觀上節省了系統開銷;
(2)在有些情況下,也許程序永遠不會真正調用show()方法,這就意味著系統無需創建BigImage對象。在這種情況下,可以顯著地提高系統的運行性能。hibernate延遲加載所采用的設計模式。當實體A B之間存在關聯關系時,當系統加載A的時候,B并沒有被加載出來,A實體里持有的B的引用全部是代理對象,只有等到A真正去訪問B的時候,系統才會從數據庫里去抓取B實體對應的記錄。
Java的動態代理去解決。
動態代理
java中動態代理主要依靠InvocationHandler 這個接口以及Proxy 這個類的方法來實現。
動態代理是在運行時生成的class,在生成它時你必須提供一組interface給它,然后該class就宣稱它實現了這些interface。你當然可以把該class的實例當作這些interface中的任何一個來用。當然,這個Dynamic Proxy其實就是一個Proxy,它不會替你作實質性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。
InvocationHandler 接口 ?
public interface InvocationHandler Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler. ?
invoke方法 Objectinvoke(Object?proxy,Method?method, Object[]?args)?
?
public?interface?Subject?? {?? ????public?void?something();?? ?? }?? (2)真實對象
?
[java] view plaincopy
public?class?RealSubject?implements?Subject?? {?? ?? ????@Override?? ????public?void?something()?? ????{?? ????????System.out.println("realSubject?do?something");?? ????}?? ?? }?? (3) 動態代理類? 動態動態類需要實現InvokeHandler接口,在這個示例里,對真實對象的方法進行了增強
?
[java] view plaincopy
public?class?DynmaticProxy?implements?InvocationHandler?? {?? ?? ????private?Object?target;?? ????public?DynmaticProxy(Object?target)?? ????{?? ????????this.target=target;?? ????}?? ????@Override?? ????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?? ????????????throws?Throwable?? ????{?? ????????System.out.println("before事務增強。。。");?? ????????Object?result=method.invoke(target,?args);?? ????????System.out.println("after?事務增強。。。。");?? ????????return?result;?? ????}?? ?? }?? (4) 測試用例
?
[java] view plaincopy
public?static?void?main(String[]?args)?? ????{?? ????????Subject?subject=new?RealSubject();?? ?????????? ????????InvocationHandler?invocationHandler=new?DynmaticProxy(subject);?? ?????????? ???????? ?????????? ????????Subject?subjectProxy=(Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(),?subject.getClass().getInterfaces(),?invocationHandler);?? ????????subjectProxy.something();?? ?????????? ????}?? 這種動態代理在AOP里被稱為AOP代理,AOP代理可以代替目標對象,AOP代理包含了目標對象的全部方法,并且AOP代理里的方法可以在執行目標方法之前、之后插入一些通用的方法。當Spring容器中的Bean實現了一個或多個接口時,Spring所創建的AOP代理就是這種動態代理。而且Spring的動態代理更加靈活,在定義InvocationHandler的時候invoke方法時,它并沒有使用硬編碼的方式決定調用那些攔截器,而是通過配置文件來決定invoke()方法中使用哪些攔截器,這就實現了更徹底的解耦。
轉載于:https://www.cnblogs.com/openlearn/p/6250406.html
總結
以上是生活随笔 為你收集整理的代理模式与动态代理 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。