一、代理介绍
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、创建接口
```java
public interface Car {
void running();
}
2.2.2、创建实现类
public class Taxi implements Car{
@Override
public 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;
}
// 第一个参数:代理对象.一般不使用;第二个参数:需要增强的方法;第三个参数:方法中的参数
@Override
public 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文件
- 代理类源码
```java
package 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.创建Enhancer
Enhancer enhancer = new Enhancer();
//2.传递目标对象的class
enhancer.setSuperclass(target.getClass());
//3.设置回调操作
enhancer.setCallback(this);
return enhancer.create();
}
//参数一:代理对象;参数二:需要增强的方法;参数三:需要增强方法的参数;参数四:需要增强的方法的代理
@Override
public 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;
}
}
- 测试
```java
Car 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