<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

    Java 代理(proxy)模式

    代理模式(Proxy Pattern)
      代理模式是常用的Java 設(shè)計(jì)模式,它的特征是代理類與委托類有同樣的接口,代理類主要負(fù)責(zé)為委托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給委托類,以及事后處理消息等。代理類與委托類之間通常會(huì)存在關(guān)聯(lián)關(guān)系,一個(gè)代理類的對象與一個(gè)委托類的對象關(guān)聯(lián),代理類的對象本身并不真正實(shí)現(xiàn)服務(wù),而是通過調(diào)用委托類的對象的相關(guān)方法,來提供特定的服務(wù)。
      如下列子:
    package proxy;
    interface Dao{
    public void insert();
    }
    class JdbcDao implements Dao{
    public void insert(){
    System.out.println("in jdbc insert");
    }
    }
    class HibernateDao implements Dao{
    public void insert(){
    System.out.println("in hibernate insert");
    }
    }
    class ProxyDao implements Dao{
    private Dao dao;
    public ProxyDao(Dao dao){
    this.dao=dao;
    }
    public void insert() {
    System.out.println("write log before invoke");
    dao.insert();
    System.out.println("write log after invoke");
    }
    }
    public class Test {
    public static void main(String[] args) {
    Dao jdbcDao =new JdbcDao();
    Dao proxydao = new ProxyDao(jdbcDao);
    proxydao.insert();
    }
    }
      運(yùn)行結(jié)果:
      write log before invoke
      in jdbc insert
      write log after invoke
      隨著Proxy的流行,Sun把它納入到JDK1.3實(shí)現(xiàn)了Java的動(dòng)態(tài)代理。動(dòng)態(tài)代理和普通的代理模式的區(qū)別,就是動(dòng)態(tài)代理中的代理類是由 java.lang.reflect.Proxy類在運(yùn)行期時(shí)根據(jù)接口定義,采用Java反射功能動(dòng)態(tài)生成的。和 java.lang.reflect.InvocationHandler結(jié)合,可以加強(qiáng)現(xiàn)有類的方法實(shí)現(xiàn)。如圖2,圖中的自定義Handler實(shí)現(xiàn) InvocationHandler接口,自定義Handler實(shí)例化時(shí),將實(shí)現(xiàn)類傳入自定義Handler對象。自定義Handler需要實(shí)現(xiàn) invoke方法,該方法可以使用Java反射調(diào)用實(shí)現(xiàn)類的實(shí)現(xiàn)的方法,同時(shí)當(dāng)然可以實(shí)現(xiàn)其他功能,例如在調(diào)用實(shí)現(xiàn)類方法前后加入Log。而Proxy類根據(jù)Handler和需要代理的接口動(dòng)態(tài)生成一個(gè)接口實(shí)現(xiàn)類的對象。當(dāng)用戶調(diào)用這個(gè)動(dòng)態(tài)生成的實(shí)現(xiàn)類時(shí),實(shí)際上是調(diào)用了自定義Handler的 invoke方法。
      Proxy類提供了創(chuàng)建動(dòng)態(tài)代理類及其實(shí)例的靜態(tài)方法。
      (1)getProxyClass()靜態(tài)方法負(fù)責(zé)創(chuàng)建動(dòng)態(tài)代理類,它的完整定義如下:
      public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException
      參數(shù)loader 指定動(dòng)態(tài)代理類的類加載器,參數(shù)interfaces 指定動(dòng)態(tài)代理類需要實(shí)現(xiàn)的所有接口。
      (2)newProxyInstance()靜態(tài)方法負(fù)責(zé)創(chuàng)建動(dòng)態(tài)代理類的實(shí)例,它的完整定義如下:
      public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws
      IllegalArgumentException
      參數(shù)loader 指定動(dòng)態(tài)代理類的類加載器,參數(shù)interfaces 指定動(dòng)態(tài)代理類需要實(shí)現(xiàn)的所有接口,參數(shù)handler 指定與動(dòng)態(tài)代理類關(guān)聯(lián)的 InvocationHandler 對象。
      以下兩種方式都創(chuàng)建了實(shí)現(xiàn)Foo接口的動(dòng)態(tài)代理類的實(shí)例:
      /**** 方式一 ****/
      //創(chuàng)建InvocationHandler對象
      InvocationHandler handler = new MyInvocationHandler(...);
      //創(chuàng)建動(dòng)態(tài)代理類
      Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
      //創(chuàng)建動(dòng)態(tài)代理類的實(shí)例
      Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
      newInstance(new Object[] { handler });
      /**** 方式二 ****/
      //創(chuàng)建InvocationHandler對象
      InvocationHandler handler = new MyInvocationHandler(...);
      //直接創(chuàng)建動(dòng)態(tài)代理類的實(shí)例
      Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);
      由Proxy類的靜態(tài)方法創(chuàng)建的動(dòng)態(tài)代理類具有以下特點(diǎn):
      動(dòng)態(tài)代理類是public、final和非抽象類型的;
      動(dòng)態(tài)代理類繼承了java.lang.reflect.Proxy類;
      動(dòng)態(tài)代理類的名字以“$Proxy”開頭;
      動(dòng)態(tài)代理類實(shí)現(xiàn)getProxyClass()和newProxyInstance()方法中參數(shù)interfaces指定的所有接口;
      Proxy 類的isProxyClass(Class<?> cl)靜態(tài)方法可用來判斷參數(shù)指定的類是否為動(dòng)態(tài)代理類。只有通過Proxy類創(chuàng)建的類才是動(dòng)態(tài)代理類;
      動(dòng)態(tài)代理類都具有一個(gè)public 類型的構(gòu)造方法,該構(gòu)造方法有一個(gè)InvocationHandler 類型的參數(shù)。
      由Proxy類的靜態(tài)方法創(chuàng)建的動(dòng)態(tài)代理類的實(shí)例具有以下特點(diǎn):
      1. 假定變量foo 是一個(gè)動(dòng)態(tài)代理類的實(shí)例,并且這個(gè)動(dòng)態(tài)代理類實(shí)現(xiàn)了Foo 接口,那么“foo instanceof Foo”的值為true。把變量foo強(qiáng)制轉(zhuǎn)換為Foo類型是合法的:
      (Foo) foo //合法
      2.每個(gè)動(dòng)態(tài)代理類實(shí)例都和一個(gè)InvocationHandler 實(shí)例關(guān)聯(lián)。Proxy 類的getInvocationHandler(Object proxy)靜態(tài)方法返回與參數(shù)proxy指定的代理類實(shí)例所關(guān)聯(lián)的InvocationHandler 對象。
      3.假定Foo接口有一個(gè)amethod()方法,那么當(dāng)程序調(diào)用動(dòng)態(tài)代理類實(shí)例foo的amethod()方法時(shí),該方法會(huì)調(diào)用與它關(guān)聯(lián)的InvocationHandler 對象的invoke()方法。
      InvocationHandler 接口為方法調(diào)用接口,它聲明了負(fù)責(zé)調(diào)用任意一個(gè)方法的invoke()方法:
      Object invoke(Object proxy,Method method,Object[] args) throws Throwable
      參數(shù)proxy指定動(dòng)態(tài)代理類實(shí)例,參數(shù)method指定被調(diào)用的方法,參數(shù)args 指定向被調(diào)用方法傳遞的參數(shù),invoke()方法的返回值表示被調(diào)用方法的返回值。
      最后看一個(gè)例子,該例子模仿spring 的AOP原理。
    package proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    class Logic{
    public void logic(){
    Dao dao = Factory.create();
    System.out.println("dynamic proxy's name: "+dao.getClass().getName());
    dao.insert();
    }
    }
    class Factory{
    static Dao create(){
    Dao dao = new JdbcDao();
    MyInvocationHandler hand = new MyInvocationHandler();
    return (Dao)hand.get(dao);
    }
    }
    interface Dao{
    public void update();
    public void insert();
    }
    class JdbcDao implements Dao{
    public void update(){
    System.out.println("in jdbc update");
    }
    public void insert(){
    System.out.println("in jdbc insert");
    }
    }
    class HibernateDao implements Dao{
    public void update(){
    System.out.println("in hibernate update");
    }
    public void insert(){
    System.out.println("in hibernate insert");
    }
    }
    class MyInvocationHandler implements InvocationHandler {
    Object o;
    public Object get(Object o){
    System.out.println("in get method of MyInvocationHandler");
    this.o = o;
    return Proxy.newProxyInstance(o.getClass().getClassLoader(),o.getClass().getInterfaces(),this);
    }
    public Object invoke(Object arg0, Method arg1, Object[] arg2)
    throws Throwable {
    System.out.println("write log before invoke");
    Object result = arg1.invoke(o, arg2);
    System.out.println("write log after invoke");
    return result;
    }
    }
    public class Test {
    public static void main(String[] args) {
    Logic l = new Logic();
    l.logic();
    }
    }
      運(yùn)行結(jié)果:
      in get method of MyInvocationHandler
      dynamic proxy's name: proxy.$Proxy0
      write log before invoke
      in jdbc insert
      write log after invoke
      結(jié)論: JDK的動(dòng)態(tài)代理并不能隨心所欲的代理所有的類。Proxy.newProxyInstance方法的第二個(gè)參數(shù)只能是接口數(shù)組, 也就是Proxy只能代理接口。

    posted on 2014-08-05 10:01 順其自然EVO 閱讀(205) 評論(0)  編輯  收藏 所屬分類: 測試學(xué)習(xí)專欄

    <2014年8月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 精品亚洲永久免费精品| 1024免费福利永久观看网站| 亚洲动漫精品无码av天堂| 最近2019免费中文字幕6| 亚洲成AV人片在线观看| 久久精品人成免费| 日本系列1页亚洲系列| 在线视频免费国产成人| 亚洲人成小说网站色| 亚洲福利精品电影在线观看| 激情无码亚洲一区二区三区| 久久亚洲国产午夜精品理论片| 黄色成人网站免费无码av| 一级特级aaaa毛片免费观看| 亚洲午夜福利精品无码| eeuss影院免费直达入口| av在线亚洲欧洲日产一区二区| 6080午夜一级毛片免费看6080夜福利 | 国产高清对白在线观看免费91| 亚洲福利视频网址| 亚洲精品在线视频| 国产免费的野战视频| 中国一级毛片视频免费看| 亚洲砖码砖专无区2023| 久久亚洲精品无码AV红樱桃| 少妇亚洲免费精品| 免费A级毛片无码免费视| 午夜精品一区二区三区免费视频 | 久久精品成人免费国产片小草 | 亚洲最大的成人网| 亚洲高清专区日韩精品| 国产99视频免费精品是看6| 新最免费影视大全在线播放| 国产亚洲高清不卡在线观看| 国产男女性潮高清免费网站| 欧亚精品一区三区免费| 一区二区免费视频| 久久成人18免费网站| 一级黄色片免费观看| 国产精品亚洲一区二区三区在线观看| 亚洲日本国产乱码va在线观看|