动态代理

2017-10-10  本文已影响0人  guan_xy
动态代理

动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。

1、与动态代理紧密关联的Java API。

1)java.lang.reflect.Proxy

2)java.lang.reflect.InvocationHandler

3)java.lang.ClassLoader


2、动态代理的实现步骤

1)创建接口

public interface IDrink {
    void drink();
}

2)创建被代理类

public class Coffee implements IDrink {

    public void drink(){
        System.out.println("喝咖啡");
    }
}

3)创建代理工具类

public class MilkHandler implements InvocationHandler {

    Object obj = null;
    public MilkHandler(Object obj){
        this.obj = obj;
    }
    
    //proxy:被代理对象  method:需要被增强的方法   args:方法的参数
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("加牛奶");
        method.invoke(obj, args);
        return null;
    }
}

4)测试

Coffee c = new Coffee();
MilkHandler h = new MilkHandler(c);
IDrink d= (IDrink) Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), h);
d.drink();

动态代理机制的特点

首先是动态生成的代理类本身的一些特点。


动态代理的优缺点

优点

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。在本示例中看不出来,因为invoke方法体内嵌入了具体的外围业务(记录任务处理前后时间并计算时间差),实际中可以类似Spring AOP那样配置外围业务。

缺点

诚然,Proxy 已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。

有很多条理由,人们可以否定对 class 代理的必要性,但是同样有一些理由,相信支持 class 动态代理会更美好。接口和类的划分,本就不是很明显,只是到了 Java 中才变得如此的细化。如果只从方法的声明及是否被定义来考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。如此种种,不得不说是一个小小的遗憾。

上一篇下一篇

猜你喜欢

热点阅读