在“CGLib CallbackFilter 接口介绍”文章中介绍了怎样去使用 CallbackFilter 接口为拦截的方法映射不同的回调 Callback。本文将介绍使用 CallbackHelper 去实现 CallbackFilter 接口类似的功能。其实,CallbackHelper 是一个实现了 CallbackFilter 接口的抽象类,它为我们实现 CallbackFilter 提供了工具类,推荐优先考虑使用该抽象类,而不是 CallbackFilter 接口。
CallbackHelper 类部分源码如下:
import net.sf.cglib.core.ReflectUtils;
import java.lang.reflect.Method;
import java.util.*;
/**
* @version $Id: CallbackHelper.java,v 1.2 2004/06/24 21:15:20 herbyderby Exp $
*/
abstract public class CallbackHelper
implements CallbackFilter
{
private Map methodMap = new HashMap();
private List callbacks = new ArrayList();
public CallbackHelper(Class superclass, Class[] interfaces)
{
// 获取所有方法的 Method 对象
List methods = new ArrayList();
Enhancer.getMethods(superclass, interfaces, methods);
Map indexes = new HashMap();
for (int i = 0, size = methods.size(); i < size; i++) {
Method method = (Method)methods.get(i);
// 调用抽象方法 getCallback() 获取回调,该方法有具体子类实现
Object callback = getCallback(method);
if (callback == null)
throw new IllegalStateException("getCallback cannot return null");
// 判断 getCallback() 返回的是否为 Callback 或者 Class 对象
boolean isCallback = callback instanceof Callback;
if (!(isCallback || (callback instanceof Class)))
throw new IllegalStateException("getCallback must return a Callback or a Class");
if (i > 0 && ((callbacks.get(i - 1) instanceof Callback) ^ isCallback))
throw new IllegalStateException("getCallback must return a Callback or a Class consistently for every Method");
// 将获取的回调 Callback 放入 callbacks 列表中
// 且将 Method 和回调在 callbacks 列表中的下标位置进行关联
Integer index = (Integer)indexes.get(callback);
if (index == null) {
index = new Integer(callbacks.size());
indexes.put(callback, index);
}
methodMap.put(method, index);
callbacks.add(callback);
}
}
// 由子类去实现,根据不同的 Method 返回不同类型的 Callback
abstract protected Object getCallback(Method method);
//...
}上面源码中,callbacks 列表用于存放所有的 Callback 回调;而 methodMap 保存 Method 和回调 Callback 在 callbacks 列表中下标关系。
本示例使用 CallbackHelper 工具类为不同的 Method 定义不同的 Callback。
(1)定义被代理的类,代码如下:
/**
* 被代理的类
* @author hxstrive.com 2021/12/29
*/
public class HelloWorld {
public String test(String msg) {
return msg;
}
public void hello() {
System.out.println("hello world");
}
}(2)客户端代码
import net.sf.cglib.proxy.CallbackHelper;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.FixedValue;
import net.sf.cglib.proxy.NoOp;
import java.lang.reflect.Method;
/**
* 验证 CallbackHelper 功能
* @author hxstrive.com 2022/1/3
*/
public class CallbackHelperDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloWorld.class);
CallbackHelper callbackHelper = new CallbackHelper(HelloWorld.class, new Class[0]) {
@Override
protected Object getCallback(Method method) {
if(method.getName().equals("test")) {
return new FixedValue() {
@Override
public Object loadObject() throws Exception {
System.out.println("call FixedValue.loadObject()");
return "Hello cglib";
}
};
} else {
return NoOp.INSTANCE;
}
}
};
enhancer.setCallbackFilter(callbackHelper);
enhancer.setCallbacks(callbackHelper.getCallbacks());
HelloWorld helloWorld = (HelloWorld) enhancer.create();
helloWorld.hello();
System.out.println("test=" + helloWorld.test("hello world"));
}
}运行上面程序,输出如下:
hello world call FixedValue.loadObject() test=Hello cglib
上面客户端代码中,test() 方法将使用 FixedValue 类型的回调 Callback。其他非 test() 方法,则使用 NoOp.INSTANCE 类型的回调。