Java动态代理模式 - 极悦
Java设计模式

Java动态代理模式

动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的.java源文件。

动态代理其实就是jdk运行期间,动态创建class字节码并加载到JVM。

动态代理的实现方式常用的有两种:使用JDK代理代理,与通过CGLIB动态代理。

jdk的动态代理

jdk动态代理是基于Java的反射机制实现的。使用jdk中接口和类实现代理对象的动态创建。

Jdk的动态要求目标对象必须实现接口,这是java设计上的要求。

从jdk1.3以来,java语言通过java.lang.reflect包提供三个类支持代理模式Proxy, Method和InovcationHandler。

⒈ InvocationHandler接口

InvocationHandler接口叫做调用处理器,负责完调用目标方法,并增强功能。

通过代理对象执行目标接口中的方法,会把方法的调用分派给调用处理器(InvocationHandler)的实现类,执行实现类中的invoke()方法,我们需要把功能代理写在invoke()方法中 。

接口中只有一个方法:

在invoke方法中可以截取对目标方法的调用。在这里进行功能增强。Java的动态代理是建立在反射机制之上的。

实现了InvocationHandler接口的类用于加强目标类的主业务逻辑。这个接口中有一个方法invoke(),具体加强的代码逻辑就是定义在该方法中的。通过代理对象执行接口中的方法时,会自动调用invoke()方法。

invoke()方法的介绍如下:

public Object invoke ( Object proxy, Method method, Object[] args)
proxy:代表生成的代理对象
method:代表目标方法
args:代表目标方法的参数

第一个参数proxy是jdk在运行时赋值的,在方法中直接使用,第二个参数后面介绍,第三个参数是方法执行的参数, 这三个参数都是jdk运行时赋值的,无需程序员给出。

⒉Method 类

invoke()方法的第二个参数为Method类对象,该类有一个方法也叫invoke(),可以调用目标方法。这两个invoke()方法,虽然同名,但无关。

public Object invoke ( Object obj, Object... args) 
 obj:表示目标对象
 args:表示目标方法参数,就是其上一层invoke方法的第三个参数

该方法的作用是:调用执行obj对象所属类的方法,这个方法由其调用者Method对象确定。

在代码中,一般的写法为method.invoke(target, args);其中,method为上一层invoke方法的第二个参数。这样,即可调用了目标类的目标方法。

⒊Proxy类

通过JDK的java.lang.reflect.Proxy类实现动态代理,会使用其静态方法newProxyInstance(),依据目标对象、业务接口及调用处理器三者,自动生成一个动态代理对象。

public static newProxyInstance ( ClassLoader loader, Class<?>[] interfaces, 
InvocationHandler handler) 
loader:目标类的类加载器,通过目标对象的反射可获取
interfaces:目标类实现的接口数组,通过目标对象的反射可获取
handler:调用处理器。 

jdk动态代理实现

jdk动态代理是代理模式的一种实现方式,其只能代理接口。

实现步骤:

① 新建一个接口,作为目标接口

② 为接口创建一个实现类,是目标类

③ 创建类实现java.lang.reflect.InvocationHandler接口,调用目标方法并增加其他功能代码

④ 创建动态代理对象,使用Proxy.newProxyInstance()方法,并把返回值强制转为接口类型。

idea创建java project

工程名称:ch02-dynamicproxy

⒈定义目标接口

⒉定义目标接口实现类

⒊定义调用处理程序

调用处理程序是实现了InvocationHandler的类,在invoke方法中增加业务功能。还需要创建有参构造,参数是目标对象。为的是完成对目标对象的方法调用。

⒋创建动态代理对象

执行流程:

类图:

cgLib代理

CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP。

使用JDK的Proxy实现代理,要求目标类与代理类实现相同的接口。若目标类不存在接口,则无法使用该方式实现。

但对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现。CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类必须能够被继承,即不能是final的类。

cglib经常被应用在框架中,例如Spring ,Hibernate等。Cglib的代理效率高于Jdk。对于cglib一般的开发中并不使用。做了一个了解就可以。

全部教程