我有一个对象的实例,需要为其创建代理以拦截其中一种方法:
所以我需要做的是:
TheObject obj = library.getObject();
TheObject proxy = createProxyObject(obj);
library.doSomethingWith(proxy);
在我看来,理论上这应该是可行的,因为对象是可序列化的,但是我找不到任何使用它的方法。
注意以下几点:我一直在尝试使用cglib,但我完全不依赖于此。如果可以在asm,javaassist或任何其他库中使用它,就可以了。
到目前为止,我使用cglib可以使用公共构造函数代理一个简单的对象:
public class SimpleObject {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
// return a random number
public int getRandom() {
return (int)(Math.random() * 100);
}
}
public void testCglibEnhancer() throws Exception {
SimpleObject object = new SimpleObject();
object.setName("object 1");
System.out.println(object.getName() + " -> " + object.getRandom());
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(object.getClass());
// intercept getRandom and always return 32
ProxyRefDispatcher passthrough = proxy -> object;
MethodInterceptor fixedRandom = (obj, method, args, proxy) -> 32;
enhancer.setCallbacks(new Callback[]{passthrough, fixedRandom});
enhancer.setCallbackFilter(method -> method.getName().equals("getRandom") ? 1 : 0);
SimpleObject proxy = (SimpleObject)enhancer.create();
System.out.println(proxy.getName() + " -> " + proxy.getRandom()); // always 32
}
但是我无法使用没有公共构造函数的对象来复制它:
public static class ComplexObject implements Serializable {
public static ComplexObject create() {
return new ComplexObject();
}
private String name;
private ComplexObject() {
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getRandom() {
return (int)(Math.random() * 100);
}
}
ComplexObject proxy = (ComplexObject)enhancer.create();
// throws IllegalArgumentException: No visible constructors
由于对象是可序列化的,所以我可以克隆它:
public static <T extends Serializable> T cloneViaSerialization(T source) throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(source);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream in = new ObjectInputStream(bis);
return (T)in.readObject();
}
public void testClone() throws Exception {
ComplexObject object1 = ComplexObject.create();
object1.setName("object 1");
ComplexObject object2 = cloneViaSerialization(object1);
object2.setName("object 2");
System.out.println(object1.getName() + " -> " + object1.getRandom());
System.out.println(object2.getName() + " -> " + object2.getRandom());
}
所以有什么办法可以让cglib(或任何库)使用这种方法?
ComplexObject object = library.getObject();
ObjectInputStream in = ... // serialised version of object
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(object.getClass());
// add callbacks etc.
// note createFromSerialized is not a existing method of
// Enhancer - it is what I'm trying to synthesise somehow
ComplexObject proxy = (ComplexObject)enhancer.createFromSerialized(in);
谢谢
使其正常工作:
对于(1),我无法获得cglib或字节伙伴来创建所需的类,所以我切换到ASM。
对于(2),我使用了一个自定义类加载器来加载包含目标类的整个jar文件。
这的确意味着我最终得到的是原始对象的克隆,而不是根据问题的代理,但这可以满足我的需要。