JDK实现动态代理
思维导图:点击打开
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CO2YWNxAzYjBDMmNDNwUjYhJ2MihTO5UzY2EGZmJGNj9CX0AzLclDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLzM3Lc9CX6MHc0RHaiojIsJye.png)
代理模式是指:为其他对象提供一种代理用以控制这个对象的访问。
在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标类之间起到中介的作用。——————百度百科《代理模式》
生活中的例子:
房产中介
代购
媒婆
在代理中控制客户端能否调用目标对象的方法。
完成目标对象的调用时,附加一些额外功能,这些额外功能就是增强功能。
比如媒婆要求中介费用
代理模式分为静态代理和动态代理
静态代理是指:代理类在程序运行前就已经定义好了.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方法中完成代理类的功能
执行结果: