天天看点

JDK实现动态代理

JDK实现动态代理

思维导图:点击打开

JDK实现动态代理

代理模式是指:为其他对象提供一种代理用以控制这个对象的访问。

在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标类之间起到中介的作用。——————百度百科《代理模式》

生活中的例子:

房产中介

代购

媒婆

在代理中控制客户端能否调用目标对象的方法。

完成目标对象的调用时,附加一些额外功能,这些额外功能就是增强功能。

比如媒婆要求中介费用

代理模式分为静态代理和动态代理

静态代理是指:代理类在程序运行前就已经定义好了.java源文件,代理类和目标类的关系在程序运行前就已经确立了。在程序运行前代理类就已经编译成了.class文件。

1.优点

容易理解

使用比较方便

2.缺点

目标类较多时,会产生大量代理类

当接口改变时,影响的目标类较多

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

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

不用创建类文件

当修改了接口中的方法时,不会影响代理类

不用给不同的目标随时创建代理

1.JDK动态代理:

使用java反射包中的类和接口实现动态代理的功能。

反射包:java.lang.reflect

使用的类:

InvocationHandler

Method

Proxy

2.CGLIB动态代理:

cglib时第三方的工具库,用于创建代理对象。

cglib的原理是继承,cglib通过继承目标类,创建其子类,在子类中重写父类中同名的方法,实现功能的修改。

因为cglib需要继承目标类,所以要求目标类不能是final的,方法也不能是final的。

cglib对于目标类的要求比较宽松,只要能继承就可以。

cglib在很多框架中使用,如mybatis,spring框架。

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

jdk的动态代理要求目标对象必须实现接口。

InvocationHandler接口叫做调用处理器,该接口只有一个抽象方法:invoke()。

在InvocationHandler接口的实现类中,实现调用目标方法并增强功能的语句就写在invoke()方法里。

proxy:代表生成的代理对象

method:代表目标方法

args:代表目标方法的参数

这三个参数都是jdk运行是赋值的,无需程序员给出。

InvocationHandler接口的invoke()方法中,第二个参数就是Method类对象,该类中也有一个invoke()方法,可以调用目标方法。这两个invoke()方法虽然同名,但是没有关系。

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

在代码中,一般写法为:

其中,method是InvocationHandler接口invoke方法的第二个参数。

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

loader:目标类的类加载器,通过目标对象的反射可以获取【目标对象.getClass().getClassLoader()】

interfaces:目标类实现的接口数组,同样可以通过目标对象的反射获取【目标对象.getClass().getInterfaces()】

h:调用处理器,也就是InvocationHandler接口实现类对象

创建目标接口,定义目标类要完成的功能

创建目标类来实现目标接口

创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能

调用目标类的方法

增强功能

使用Proxy类的静态方法,创建代理对象。并把返回值也就是代理对象转为接口类型。

定义目标类要完成的功能

在invoke方法中完成代理类的功能

执行结果: