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

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

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

    隨筆-159  評論-114  文章-7  trackbacks-0
    某些接口的實現類,我們要做一個代理,來代理對這些實現類對象的方法調用。

    public class SomeClassImpl {
      
    private String userName;  
      
    public SomeClassImpl(final String userName) {
        
    this.userName = userName;
      }
        
        
    public void someMethod( ) {
        System.out.println(
    this.userName);
      }

      
    public void someOtherMethod(final String text) {
        System.out.println(text);
      }

    }


    該類的簡單代理

    public class SomeClassProxy {
      
    private final SomeClassImpl impl;
      
    public SomeClassProxy(final SomeClassImpl impl) {
        
    this.impl = impl;
      }


      
    public void someMethod( ) {
        
    this.impl.someMethod( );
      }

      
    public void someOtherMethod(String text) {
        
    this.impl.someOtherMethod(text);
      }

    }


    使用代理的原因

    有一些原因,你需要做代理來在你的應用和實現類之間插入一些有用的代碼。

    1.實現類的源碼不能拿到。比如第三方實現的。

    2.有時代理要添加的代碼與實現類的功能沒有直接聯系,不能將那些代碼放入實現者內部,會破化一種對象應該只實現一個概念。

    3.實現者所展現出來的特點應該對各種用戶做隱藏。

    4.你可能想隱藏實現方法的名字給用戶,出于一些安全的考慮。這需要代理有一個特殊的面貌,也就是方法名與真正實現者的方法名不同。

    5.也許要的功能依賴于對象所在的上下文。例如,如果計算機連接到工廠的機械手臂,不需要網絡代碼來訪問手臂,但是工廠的另一端確實需要這段代碼。

    6.也許這些功能只是用于在開發階段。例如,你能使用一個代理來實現程序的跟蹤,來記錄對象的調用次數。這代碼在真正部署時不需要。

    7.實現者的位置或許是變化的,就好像企業編程。對象進行實際的操作在企業級網絡中,經常更換位置取決于負載平衡和故障轉移。你可能需要一個智能的代理定位該對象來提供服務給其他用戶。

    工廠的應用

    獲得一個代理,經常通過一個工廠對象獲得。使用工廠的原因是因為你不用特別關心哪一種實現者來實現你的功能,只要他們能正確實現就好了。

    public class SomeClassFactory {
      
    public final static SomeClassProxy getProxy( ) {
      SomeClassImpl impl 
    = new SomeClassImpl(System.getProperty("user.name"));
        
    return new SomeClassProxy(impl);
      }

    }


    public class DemoProxyFactory {
      
    public static final void main(final String[] args) {
        SomeClassProxy proxy 
    = SomeClassFactory.getProxy( );
        proxy.someMethod( );
        proxy.someOtherMethod(
    "Our Proxy works!");
      }

    }



    代理與接口

    用戶有時并不想知道實現的具體細節,也就是到底是代理還是真正實現者完成的功能。如果像上面的工廠類的實現,用戶必須知道什么情況下,使用何種代理,這對于用戶的使用提高了難度。需要特殊方法來引用合適的代理,Java的接口就使用用于解決這樣的問題。

    為了隔離實現代理的細節,你能使用接口來描述功能。

    public interface SomeClass {
      [
    public abstractvoid someMethod( );
      [
    public abstractvoid someOtherMethod(final String text);
    }


    public class SomeClassImpl implements SomeClass {
      
    // same as before
    }


    public class SomeClassProxy implements SomeClass {
      
    // same as before
    }


    public class SomeClassCountingProxy implements SomeClass {
      
    // same as before
    }


    public class SomeClassFactory {
      
    public static final SomeClass getSomeClassProxy( ) {
          SomeClassImpl impl 
    = new SomeClassImpl(System.getProperty("user.name"));
    if (LOGGER.isDebugEnabled( )) {
              
    return new SomeClassCountingProxy(impl);      
          }
     else {
              
    return new SomeClassProxy(impl);      
          }

      }

    }


    使用

    public class DemoInterfaceProxy {
      
    public static final void main(final String[] args) {
        SomeClass proxy 
    = SomeClassFactory.getSomeClassProxy( );
        proxy.someMethod( );
        proxy.someOtherMethod(
    "Our Proxy works!");
      }

    }



    提示

    if (proxy instanceof SomeClassCountingProxy) {

     System.out.println(((SomeClassCountingProxy)proxy).getInvocationCount());

    }

    一個靜態代理的實例代碼:

    public class SomeClassCountingProxy {
      
    private final SomeClassImpl impl;
      
    private int invocationCount = 0;
      
    public SomeClassCountingProxy(final SomeClassImpl impl) {
        
    this.impl = impl;
      }

      
    public int getInvocationCount( ) {
        
    return invocationCount;
      }

      
    public void someMethod( ) {
        
    this.invocationCount++;
        
    this.impl.someMethod( );
      }

      
    public void someOtherMethod(String text) {
        
    this.invocationCount++;
        
    this.impl.someOtherMethod(text);
      }

    }



    靜態代理的缺點

    當給不同的對象,編寫相同功能的代理類時,會發現需要做很多相同的工作,產生很多相同的代碼。例如,都是對實現對象的調用進行計數,對于不同對象,要有不同的代理,但是實際上,他們的邏輯是一樣的。這么多代碼不容易維護,一個改了,所有的都要修改,是很可怕的。

    動態代理,主要使用反射來實行。

    主要工作是實現一個InvocationHandler,他會截住對實現者的調用,進行一些邏輯,這時在將請求發給實現者,一旦實現者返回,invocationhandler也返回結果。

    public class MethodCountingHandler implements InvocationHandler {
      
    private final Object impl;
      
    private int invocationCount = 0;
      
    public MethodCountingHandler(final Object impl) {
        
    this.impl = impl;
      }

      
    public int getInvocationCount( ) {
        
    return invocationCount;
      }

      
    public Object invoke(Object proxy, Method meth, Object[] args)
                    
    throws Throwable {
        
    try {
          
    this.invocationCount++;
          Object result 
    = meth.invoke(impl, args);
          
    return result;
        }
     catch (final InvocationTargetException ex) {
          
    throw ex.getTargetException( );
        }

      }

    }


    這代理提供著與靜態代理相同的功能。然而,他使用反射來完成工作的,當用戶執行代理的方法時,invocation handler被替換成實現者來被調用。在其內部增加了invocationCount的值并轉發調用給實現者通過調用Method對象的invoke()方法。一旦調用完成,實現將會返回一個valuehandler。可以將value返回給調用者。

    When writing invocation handlers, be careful of methods that return primitive types. The JDK will wrap primitive types in their corresponding wrapper types to return them from a reflexive invocation. The problem is that your handler can return null, but the actual method being called on the implementation cannot. Therefore, if you try to return null after calling a method that returns a primitive, the proxy class will throw a NullPointerException. This NullPointerException applies to the return value, not to the parameters of the method.

    可以在invoke方法中加入復雜的邏輯。

    得到一個實現者接口的實現者(這里當然就是那個動態代理對象),通過工廠。

    public class SomeClassFactory {
      
    public static final SomeClass getDynamicSomeClassProxy( ) {
        SomeClassImpl impl 
    = new SomeClassImpl(System.getProperty("user.name"));
        InvocationHandler handler 
    = new MethodCountingHandler(impl);
        Class[] interfaces 
    = new Class[] { SomeClass.class };
        ClassLoader loader 
    = SomeClassFactory.class.getClassLoader( );
        SomeClass proxy 
    = (SomeClass)Proxy.newProxyInstance(loader, 
                                                            interfaces, 
                                                            handler);
        
    return proxy;
      }

    }



    In this version of the factory method, SomeClass is an interface implemented by the actual implementation, named SomeClassImpl. This allows you to tell the Proxy class to generate a new proxy that implements the interface SomeClass and uses the invocation handler.

     

    One limitation of this system is that the implementation class must implement the interfaces used in the proxy. Therefore, if the implementation did not implement the interface in the first place and the source code is out of your control, this paradigm won't work.

    public class DemoDynamicProxy {
      
    public static final void main(final String[] args) {
        SomeClass proxy 
    = SomeClassFactory.getDynamicSomeClassProxy( );
        proxy.someMethod( );
        proxy.someOtherMethod(
    "Our Proxy works!");
      }
      
    }


    InvocationHandler handler = Proxy.getInvocationHandler(proxy);

    if (handler instanceof MethodCountingHandler) {

      System.out.println(((MethodCountingHandler)handler).getInvocationCount( ));

    }

    ===========================================================================================

     

    package com.ljl.proxy;

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.List;
    import java.util.Vector;

    public class VectorProxy implements InvocationHandler{

        
    private Object proxyobj;
        
    public VectorProxy(Object obj) {
            
    super();
            
    this.proxyobj = obj;
        }


        
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            
            System.out.println(
    "before calling " + method);
            
    if(args!=null)
            
    {
                
    for(int i = 0; i < args.length;i++)
                
    {
                    System.out.println(args[i]
    +" ");
                }

            }

            Object o 
    = method.invoke(proxyobj,args);        
            System.out.println(
    "after calling " + method);
            
            
    return o;
        }

        
        
    public static Object factory(Object obj)
        
    {
            Class cls 
    = obj.getClass();
            
    return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new VectorProxy(obj));
        }

        
        
    public static void main(String[] args)
        
    {
            List v 
    = null;
            v 
    = (List)factory(new Vector(10));
            v.add(
    "ljl");
            v.add(
    "hus");
        }


    }



    posted on 2006-01-30 18:27 北國狼人的BloG 閱讀(2025) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     
    主站蜘蛛池模板: 亚洲一级毛片免费观看| 亚洲中文字幕久久精品无码APP| 久久精品国产亚洲AV网站| 一级做a爰全过程免费视频毛片 | 特级毛片免费播放| 国产亚洲福利一区二区免费看| 亚洲国产AV一区二区三区四区| 在线免费一区二区| 亚洲gay片在线gv网站| 国产高清免费在线| 午夜在线亚洲男人午在线| 免费人成视频在线观看视频| 麻豆一区二区三区蜜桃免费| 亚洲精品456播放| 精品免费久久久久国产一区 | 在线观看亚洲免费视频| 亚洲AV无码一区二区三区电影 | 亚洲精品国产综合久久久久紧| 成人看的午夜免费毛片| 激情无码亚洲一区二区三区 | 国产亚洲综合成人91精品| 国产偷伦视频免费观看| 911精品国产亚洲日本美国韩国 | 我们的2018在线观看免费高清| ASS亚洲熟妇毛茸茸PICS| 国产精品免费综合一区视频| 国产V片在线播放免费无码 | 四虎免费在线观看| 羞羞网站在线免费观看| 亚洲国产成人片在线观看无码| 国产精品成人观看视频免费| 久久久精品午夜免费不卡| 久久精品国产亚洲AV无码娇色| 毛片a级毛片免费观看免下载| 老司机午夜性生免费福利| 亚洲av中文无码乱人伦在线r▽ | 亚洲理论片中文字幕电影| 国产精品99久久免费| a毛片免费全部在线播放**| 亚洲av无码片区一区二区三区| 国产不卡免费视频|