<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 閱讀(2023) 評論(0)  編輯  收藏

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


    網站導航:
     
    主站蜘蛛池模板: 亚洲免费在线视频| 免费国产成人高清视频网站| 国产精品亚洲片夜色在线| 国产又粗又猛又爽又黄的免费视频 | 国产成人精品日本亚洲网址| 日韩一区二区在线免费观看 | www永久免费视频| 久久亚洲日韩看片无码| 国产一级高清视频免费看| 国产精品亚洲αv天堂无码| 最近最新高清免费中文字幕 | 精品日韩99亚洲的在线发布| 中文字幕天天躁日日躁狠狠躁免费| 亚洲va久久久噜噜噜久久男同| 一区二区三区观看免费中文视频在线播放| 亚洲av无码潮喷在线观看| 亚洲黄色免费网站| 亚洲精品无码高潮喷水A片软| 免费人成年轻人电影| 国产99久久久久久免费看| 亚洲丁香色婷婷综合欲色啪| 亚洲电影在线免费观看| 亚洲七久久之综合七久久| 亚洲高清视频一视频二视频三| 亚欧洲精品在线视频免费观看 | 日韩午夜理论免费TV影院| 亚洲H在线播放在线观看H| 免费人成在线观看网站品爱网日本 | 99re6热视频精品免费观看| 亚洲一卡2卡3卡4卡5卡6卡| 亚洲av无码不卡私人影院| 波多野结衣免费一区视频| 亚洲一区在线视频观看| 亚洲AV永久无码精品一区二区国产 | 美女的胸又黄又www网站免费| 亚洲另类激情综合偷自拍图| 亚洲天堂免费在线| 国产日韩AV免费无码一区二区三区| 青青草原精品国产亚洲av| 免费萌白酱国产一区二区| 欧洲精品99毛片免费高清观看|