前言
曾经尝试在网上搜索 cglib的两种代理方式,搜到的结果基本全是讲动态代理的两种方式而非Cglib动态代理的两种方式。
按我的理解Cglib动态代理有两种,JDK的有一种,一共应该是三种动态代理才对。本文灵感来源:在学习Spring框架的AOP模块时,在被代理方法(此处假设该方法的持有类为TestBean)里执行System.out.println(this.getClass());打印的结果是TestBean的类名,这与我期望结果有些偏差,我觉得应该是输出子类的类名。于是便对Cglib的代理模式和调用过程进行探究。
代理类通过执行回调类的intercept方法来对方法进行代理:
回调类需要实现的接口:MethodInterceptor
实现方法:intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy);
obj : 代理对象
method : 被代理对象的方法
args : 方法的参数
methodProxy : 代理对象的方法(与method的方法不同名,但是有对应关系,其方法实现与被代理对象对应方法的实现一致,而代理对象中与method同名的方法则被改写为:一部分判断逻辑和调用回调对象的intercept方法)
两种代理方式
1、继承非持有式代理
创建代理过程(无需额外创建被代理的对象)
① 创建Enhancer对象
② 用Enhancer对象设置代理类的父类(被代理类)
③ 创建回调对象(回调类实现 MethodInterceptor 接口)
④ 用Enhancer对象设置回调对象
⑤ 用Enhancer对象创建代理对象调用方式
在回调类的intercept函数中,执行:①前置输出 ②调用被代理对象的方法 ③后置输出
注意点:② 中需使用 methodProxy 对象调用 invokeSuper 方法即:methodProxy.invokeSuper(obj,args); 参数名意义在上边
2、继承持有式代理
- 创建代理过程
① 创建被代理对象
② 创建回调对象,并将被代理对象存入回调对象的target变量中
③ 使用Enhancer的create(Class clazz, MethodInterceptor callBack)方法创建代理对象- 调用方式
在回调类的interpret函数中,执行:①前置输出 ②调用被代理对象的方法 ③后置输出
注意点:② 中需要使用 method对象调用invoke方法,即:method.invoke(target,args);参数名意义在上边。此处也可执行methodProxy.invokeSuper(obj, args); 但如此调用target对象就变得无意义,而且代理方式同1 继承非持有式代理没有区别了
比较:
在代理方式1中,在客户端(main函数)中,生成的代理类调用的方法内部如果有调用该类的方法时,会对被调用的方法进行代理。
而在代理方式2中,不会。
示例(对上边比较的验证)
TestMain .java
package com.cglib.test;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.io.IOException;
import java.lang.reflect.Method;
public class TestMain {
public static void main(String[] args) throws InterruptedException, IOException {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestBean.class);
enhancer.setCallback(new TBProxy());
TestBean tb1 = (TestBean) enhancer.create();
TestBean tb2 = (TestBean) Enhancer.create(TestBean.class, new TBProxyx(new TestBean()));
tb1.print();
System.out.println("\n\n\n");
tb2.print();
}
// 被代理类
static class TestBean {
public void print() {
System.out.println("i am printing something");
t();
}
public void t() {
System.out.println("=== im t() ===");
}
}
// 代理方式1
static class TBProxy implements MethodInterceptor {
public TBProxy() {
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("============= start ================");
Object result = methodProxy.invokeSuper(obj, args);
System.out.println("============= end ================");
return null;
}
}
// 代理方式2
static class TBProxyx implements MethodInterceptor {
public TBProxyx(Object obj) {
this.target = obj;
}
Object target;
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("============= startaaa ================");
Object result = method.invoke(target, args);
System.out.println("============= endaaa ================");
return result;
}
}
}
输出:(第一种,t()函数的打印结果上下有前后置输出,而第二种没有。)
============= start ================
i am printing something
============= start ================
=== im t() ===
============= end ================
============= end ================
============= startaaa ================
i am printing something
=== im t() ===
============= endaaa ================
对生成类的分析见下一节内容