zoukankan      html  css  js  c++  java
  • [转]Java 静态代理和动态代理

    载自http://kuangbaoxu.javaeye.com/blog/192804
    1. 代理模式主要有两种:静态代理和动态代理

    2. 静态代理:

    比如要在输出“HelloWorld”前打印一个字符串“Welcome”

    A:先定义一个接口类

    1package ttitfly.proxy;    
    2   
    3public interface HelloWorld {    
    4    public void print();    
    5//  public void say();    
    6}
     

    B: 定义一个该接口的实现类

    java 代码

     1package ttitfly.proxy;    
     2   
     3public class HelloWorldImpl implements HelloWorld{    
     4   
     5    public void print(){    
     6        System.out.println("HelloWorld");    
     7    }
        
     8//  public void say(){    
     9//      System.out.println("Say Hello!");    
    10//  }    
    11}
        

    C:定义一个静态代理类

     1package ttitfly.proxy;    
     2   
     3public class StaticProxy implements HelloWorld{    
     4   
     5    public HelloWorld helloWorld ;    
     6    public StaticProxy(HelloWorld helloWorld){    
     7        this.helloWorld = helloWorld;    
     8    }
        
     9        
    10    public void print(){    
    11        System.out.println("Welcome");    
    12        //相当于回调    
    13        helloWorld.print();    
    14    }
        
    15        
    16//  public void say(){    
    17//      //相当于回调    
    18//      helloWorld.say();    
    19//  }    
    20}
        

    D: 一个测试类:

     1package ttitfly.proxy;    
     2   
     3public class TestStaticProxy {    
     4   
     5    public static void main(String[] args){    
     6        HelloWorld helloWorld = new HelloWorldImpl();    
     7        StaticProxy staticProxy = new StaticProxy(helloWorld);    
     8        staticProxy.print();    
     9            
    10//      staticProxy.say();    
    11    }
        
    12}
        

    可以看出静态代理类有一个很不爽的缺点:当如果接口加一个方法(把上面所有的代码的注释给去掉),所有的实现类和代理类里都需要做个实现。

    这就增加了代码的复杂度。动态代理就可以避免这个缺点。 

    3 。动态代理 


    动态代理与普通的代理相比较,最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),这样,在接口方法数量比较多的时候,我们可以进行灵活处理,

    而不需要像静态代理那样每一个方法进行中转。

    动态代理类只能代理接口代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类

    代理类: 

     1package ttitfly.proxy;        
     2       
     3import java.lang.reflect.InvocationHandler;        
     4import java.lang.reflect.Method;        
     5import java.lang.reflect.Proxy;        
     6//动态代理类只能代理接口,代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类        
     7public class DynamicProxy implements InvocationHandler{        
     8            
     9    private Object object;         
    10    //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。    
    11    //Proxy.newProxyInstance的第三个参数是表明这些被拦截的方法执行时需要执行哪个InvocationHandler的invoke方法    
    12    public Object bindRelation(Object object){         
    13        this.object = object;        
    14        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);         
    15    }
             
    16    //拦截关联的这个实现类的方法被调用时将被执行        
    17    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         
    18        System.out.println("Welcome");        
    19        Object result = method.invoke(object, args);         
    20        return result;        
    21    }
            
    22       
    23}
            


    测试类:

     1package ttitfly.proxy;        
     2       
     3public class TestDynamicProxy {        
     4    public static void main(String[] args){        
     5        HelloWorld helloWorld = new HelloWorldImpl();        
     6        DynamicProxy dp = new DynamicProxy();        
     7        //在这里绑定的是HelloWorld,也就是HelloWorld是被代理接口。所以绑定关系时,需要传递一个HelloWorld的实现类的实例化对象。        
     8        HelloWorld helloWorld1 = (HelloWorld)dp.bindRelation(helloWorld);         
     9        helloWorld1.print();         
    10        helloWorld1.say();        
    11            
    12        //helloWorld2将不被拦截    
    13        HelloWorld helloWorld2 = new HelloWorldImpl();    
    14        helloWorld2.print();         
    15        helloWorld2.say();    
    16            
    17    }
            
    18}
            

    在测试类里调用实现类的print和say方法,因为代理类里代理了HelloWorld的所有方法。所以就不需要像静态代理类那样一一实现了。
    [本来想自己写个类似的东西,不过发现javaeye的这篇写的已经很好了.转载过来学习一下.
     javaeye的代码copy功能真好用!.]





  • 相关阅读:
    [ 随手记 4 ]C/C++ 模板(Template)使用/重载区别
    [ 随手记 3 ] 堆区/栈区/堆栈/队列
    [ 随手记 2 ] C/C++ 数组/指针/传数组到函数/指针数组/数组指针
    柯西方程的另外一种解法
    十分强大的CC抛物线定理(数学)
    模板_BIT
    模板_SEG_TREE
    模板_SPLAY
    模板_LCA
    NOIP游(GUNCU)记
  • 原文地址:https://www.cnblogs.com/redcoatjk/p/3562430.html
Copyright © 2011-2022 走看看