Java动态代理

Artio 于 2022-04-25 发布

代理是Java中的一种设计模式,主要用于提供对目标对象另外的访问方式,即通过代理对象访问目标对象。这样,就可以在目标对象实现的基础上,加强额外的功能操作,实现拓展目标对象的功能。

代理模式的关键点在于代理对象和目标对象,代理对象是对目标对象的扩展,并且代理对象对调用目标对象。

Java代理的方式有3种:静态代理、动态代理和CGLib代理

静态代理

所谓静态代理就是当确定代理对象和被代理对象后,就无法再去代理另一个对象。同理,在Java静态代理中,如果我们想要实现另一个代理,就需要重新写一个代理对象。

总而言之,在静态代理中,代理类和被代理类实现了同样的接口,代理类同时持有被代理类的引用。当我们需要调用被代理类的方法时,可以通过调用代理类的方法实现

动态代理

静态代理的优势很明显,即允许开发人员在不修改已有代码的情况下完成一些增强功能的需求。但是静态代理的缺点也很明显,它的使用会由于代理对象要实现与目标对象一致的接口,从而产生过多的代理类,造成冗余;其次,大量使用静态代理会使项目不易维护,一旦接口增加方法,目标对象与代理对象就要进行修改。而动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。这就意味着Java中的动态 使用了反射,因此动态代理其实是基于反射机制的一种代理。

动态代理与静态代理的区别在于,通过动态代理可以实现多个需求。动态代理是通过实现接口的方式来实现代理,具体来说,动态代理是通过Proxy类创建代理对象,然后将接口方法代理给InvocationHandler接口完成的。

动态代理的关键有两个,即上边提到的Proxy类以及InvocationHandler接口。

Proxy类

在JDK中,java提供了Java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类,这两个类互相配合,其中Proxy类是入口,Proxy类是用来创建一个代理对象的类,它提供了以下方法:

在上述方法中,最常用的newProxyInstance方法,该方法的作用是创建一个代理类对象,它接收三个参数:loader、interfaces以及h:

InvocationHandler接口

Java.lang.reflect InvocationHandler,主要方法为 Object invoke (Object proxy, Method method, Object[] args),该方法定义了代理对象调用方法时希望执行的动作,用于集中处理在动态代理类对象上的方法调用。Invoke有三个参数:proxy、method、args,含义如下:

CGLib代理

CGLib(Code Generation Library)是⼀个第三⽅代码⽣成类库,运⾏时在内存中动态⽣成⼀个⼦类对象,从⽽实现对⽬标对象功能的扩展。与动态代理不同的是,动态代理是基于Java反射机制实现的,必须实现接⼝的业务类才能使⽤这种办法⽣成代理对象。⽽CGLib则是基于ASM机制实现,通过⽣成业务类的⼦类作为代理类。

与动态代理相⽐,动态代理限制了只能基于接⼝设计,对于没有接⼝的情况,JDK⽅式⽆法解决,⽽CGLib则可以解决这⼀问题;其次,CGLib采⽤了⾮常底层的字节码技术,性能表现也很不错。