一、代理介绍
1.1、代理的种类
- 静态代理
- 动态代理
二、JDK 代理
2.1、jdk 代理相关类
- InvocationHandler 代理执行接口
```java
//代理执行接口
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
}throws Throwable;
- Proxy 用于提供静态方法创建动态代理类和实例<a name="etUmc"></a>### 2.2、jdk 代理使用<a name="B5lcR"></a>#### 2.2.1、创建接口```javapublic interface Car {void running();}
2.2.2、创建实现类
public class Taxi implements Car{@Overridepublic void running() {System.out.println("The taxi is running.");}}
2.2.3、创建代理执行类
/*** 代理工厂*/public class JDKProxyFactory implements InvocationHandler {private Object target;public JDKProxyFactory(Object target) {super();this.target = target;}// 创建代理对象public Object createProxy() {// 1.得到目标对象的类加载器ClassLoader classLoader = target.getClass().getClassLoader();// 2.得到目标对象的实现接口Class<?>[] interfaces = target.getClass().getInterfaces();// 3.第三个参数需要一个实现invocationHandler接口的对象Object newProxyInstance = Proxy.newProxyInstance(classLoader, interfaces, this);return newProxyInstance;}// 第一个参数:代理对象.一般不使用;第二个参数:需要增强的方法;第三个参数:方法中的参数@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("这是增强方法前......");Object invoke = method.invoke(target, args);System.out.println("这是增强方法后......");return invoke;}}
2.2.4、运行
Car car=new Taxi();JDKProxyFactory jdkProxyFactory=new JDKProxyFactory(car);Car proxy = (Car) jdkProxyFactory.createProxy();proxy.running();
2.3、查看jdk 生成的代理类
生成的代理类名称
//全限定类名.$Proxy序号com.sun.proxy.$Proxy0
添加 vm 参数,输出代理类 ```shell -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
会在项目中的【com.sun.proxy】目录中找到这个.class文件
- 代理类源码```javapackage com.sun.proxy;import cn.hdj.springbootaopdemo.proxy.jdk.Car;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy4 extends Proxy implements Car {private static Method m1;private static Method m3;private static Method m2;private static Method m0;public $Proxy4(InvocationHandler var1) throws {super(var1);}public final boolean equals(Object var1) throws {try {return (Boolean)super.h.invoke(this, m1, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final void running() throws {try {super.h.invoke(this, m3, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final String toString() throws {try {return (String)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws {try {return (Integer)super.h.invoke(this, m0, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m3 = Class.forName("cn.hdj.springbootaopdemo.proxy.jdk.Car").getMethod("running");m2 = Class.forName("java.lang.Object").getMethod("toString");m0 = Class.forName("java.lang.Object").getMethod("hashCode");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}}
三、CGLib 代理
3.1、相关类
- MethodInterceptor
方法拦截器
- Enhancer
增强类,用于生成动态代理子类
- FastClass
主要思想就是在为了避免方法调用时,过度使用反射造成调用慢的问题
给每一个方法一个签名,遇到这个签名时,直接显示调用实现类的实现方法,
3.2、cglib 使用
创建代理 ```java public class CglibProxyFactory implements MethodInterceptor { //得到目标对象 private Object target;
//使用构造方法传递目标对象 public CglibProxyFactory(Object target) {
super();this.target = target;
}
//创建代理对象 public Object createProxy(){
//1.创建EnhancerEnhancer enhancer = new Enhancer();//2.传递目标对象的classenhancer.setSuperclass(target.getClass());//3.设置回调操作enhancer.setCallback(this);return enhancer.create();
}
//参数一:代理对象;参数二:需要增强的方法;参数三:需要增强方法的参数;参数四:需要增强的方法的代理@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("这是增强方法前......");Object invoke = methodProxy.invoke(target, args);System.out.println("这是增强方法后......");return invoke;}
}
- 测试```javaCar car=new Taxi();CglibProxyFactory factory=new CglibProxyFactory(car);Car proxy = (Car) factory.createProxy();proxy.running();
3.3、查看生成的代理类
配置 输出代理类
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./target");
生成的代理类 ```
命名
类名EnhancerByCGLIB内存地址
目标代理类
TaxiEnhancerByCGLIBc0b91a45
目标代理类的 FastClass
TaxiEnhancerByCGLIBc0b91a45FastClassByCGLIB287524b5
目标类 的 FastClass代理类
TaxiFastClassByCGLIBc2a0126 ```
四、JDK代理和 CGLib 代理的区别?
- JDK Proxy 是 Java 语言自带的功能,无需通过加载第三方类实现;
- Java 对 JDK Proxy 提供了稳定的支持,并且会持续的升级和更新 JDK Proxy,例如 Java 8 版本中的 JDK Proxy 性能相比于之前版本提升了很多;
- JDK Proxy 是通过拦截器加反射的方式实现的;
- JDK Proxy 只能代理继承接口的类;
- JDK Proxy 实现和调用起来比较简单;
- CGLib 是第三方提供的工具,基于 ASM 实现的,性能比较高;
- CGLib 无需通过接口来实现,它是通过实现子类的方式来完成调用的。
CGLib 执行方法不需要使用反射,本身生成了 FastClass 维护了目标类的的方法和索引的映射
参考
- https://www.cnblogs.com/zjfjava/p/13919437.html
