我有一个对象的实例,需要为其创建代理以拦截其中一种方法:
- 该对象实现了一个接口,但我需要代理完整类型,而不仅仅是实现该接口。
- 我不知道对象的确切类型,只知道其接口类。
- 没有可访问的公共构造函数。
- 对象是可序列化的。
- 我具有阅读该库代码的完全可访问性,但是没有能力对其进行任何更改。
所以我需要做的是这样的:
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);
谢谢