JDK动态代理和CGLib动态代理
JDK 动态代理是 JVM 根据传进来的对象,动态的创建**对象的代理对象**并返回。
CGLib 动态代理比较复杂,它是通过继承的方式来实现**类的代理**。
JDK 动态代理
实现步骤:
- 定义业务接口
- 实现业务接口
定义代理类
public class JDKProxy {
/** * @param obj * 需要代理的对象 * @return 返回代理对象 */
@SuppressWarnings("unchecked")
public static <T> T proxy(final T obj) {
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
/** * proxy: method:被代理对象的方法 args:被代理对象的方法需要的参数 */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 增强逻辑
// 调用原方法
Object result = method.invoke(obj, args);
// 增强逻辑
return result;
}
});
}
}
CGLib 动态代理
原理:
- 自定义类 A
- 使用 CGLib 在内存中创建一个没有名称的动态类 B,返回 B 的引用 C
- 通过引用 C 指定 A 和 B 的继承结构,B extends A
定义方法调用拦截,在拦截中增强逻辑,并执行原操作
public class CGLibProxy {
@SuppressWarnings("unchecked")
public static <T> T proxy(Class<T> clazz) {
// 在内存中创建动态类
Enhancer dynamicClass = new Enhancer();
// 设置动态类的父类
dynamicClass.setSuperclass(clazz);
// 创建方法调用拦截
Callback callback = new MethodInterceptor() {
/** * proxy:代理对象 * method:被拦截的方法对象 * args:方法参数 * methodProxy:被拦截的方法对象的代理对象 */
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
// 增强逻辑
// 调用父类的方法,由于继承重写的特性,最终会执行子类的方法
// 不使用这个方法:methodProxy.invoke(proxy, args);
Object result = methodProxy.invokeSuper(proxy, args);
// 增强逻辑
return result;
}
};
dynamicClass.setCallback(callback);
// 返回动态类实例
return (T) dynamicClass.create();
}
}
如何理解 CGLib 动态代理的实现?
// 例如:Student extends Person
// 创建 Student 对象,但以 Person 展现
Person p = new Student();
// 我们知道,如果 Person 中没有 speak()方法,那么这里编译不会通过
// 程序运行时,并不会调用 Person 中 speak()方法的实现,而是调用 Student 中的实现
p.speak();// 从继承和重写上看,我们应该知道为什么在 CGLib 中
// 不使用这个方法:methodProxy.invoke(proxy, args);
// 而调用 invokeSuper 方法的原因
Object result = methodProxy.invokeSuper(proxy, args);
还没有评论,来说两句吧...