在 CGLib 中,Dispatcher 接口用来调度 Enhancer 回调。这与 LazyLoader 接口相同,但需要分开,以便 Enhancer 知道要生成哪种类型的代码。
Dispatcher 接口继承了 Callback 接口,Callback 接口没有定义任何方法(即一个标识接口,类似 JDK 的 java.io.Serializable 接口),Enhancer 使用的所有回调接口都扩展了这个接口。
Dispatcher 接口除了继承 Callback 接口外,自己还定义了一个 loadObject() 方法,它的定义如下:
java.lang.Object loadObject() throws java.lang.Exception
返回原始方法调用应该调度的对象,每次方法调用都会调用此方法。
(1)创建被代理的类,代码如下:
/**
* 被代理的类
* @author hxstrive.com 2021/12/29
*/
public class HelloWorld {
private String msg;
public HelloWorld(String msg) {
this.msg = msg;
}
public HelloWorld() {
this("hello world");
}
public String test(){
return this.msg;
}
}(2)创建客户端代码,通过 Enhancer 类的 setCallback() 方法设置 Dispatcher 类型回调方法。然后在 Dispatcher 回调的 loadObject() 方法中返回目标实例对象且打印 “call loadObject()” 日志信息。代码如下:
import com.hxstrive.cglib.callback.demo2.HelloWorld;
import net.sf.cglib.proxy.Dispatcher;
import net.sf.cglib.proxy.Enhancer;
/**
* 验证 setCallback() 设置 Dispatcher 接口
* @author hxstrive.com 2021/12/31
*/
public class CglibDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloWorld.class);
enhancer.setCallback(new Dispatcher() {
@Override
public Object loadObject() throws Exception {
System.out.println("call loadObject()");
return new HelloWorld("dispatcher test");
}
});
HelloWorld sample = (HelloWorld) enhancer.create();
System.out.println("sample.test():\n" + sample.test());
System.out.println("\nsample.toString():\n" + sample.toString());
System.out.println("\nsample.getClass():\n" + sample.getClass());
System.out.println("\nsample.hashCode():\n" + sample.hashCode());
}
}运行程序输出如下:
call loadObject() sample.test(): dispatcher test call loadObject() sample.toString(): com.hxstrive.cglib.callback.demo2.HelloWorld@108c4c35 sample.getClass(): class com.hxstrive.cglib.callback.demo2.HelloWorld$$EnhancerByCGLIB$$d0dd83e4 call loadObject() sample.hashCode(): 1288354730
根据上面输出信息可知,当我们调用 HelloWorld 类的 test()、toString()、hashCode() 方法时,每次都会调用一次 CGLib Enhancer 的回调 Dispatcher 的 loadObject() 方法。这也说明,每调用一次 HelloWorld 代理类的非 final 方法,CGLib 都会创建一个新的 HelloWorld 对象。