我正在尝试将调用处理程序序列化为文件。我只是试图序列化以下部分,因为它是程序中唯一会改变的部分:
public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
System.out.println("BEFORE");
method.invoke(original, args);
System.out.println("AFTER");
//System.out.println(method);
return null;
}
我收到以下错误
run:Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous tree type: <any>
at jdkproxydemo.JdkProxyDemo.main(JdkProxyDemo.java:69)
C:\Users\ACK\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 1 second)
以下是完整代码:
public class JdkProxyDemo {
interface If {
int originalMethod(String s);
}
static class Original implements If {
public int originalMethod(String s) {
System.out.println(s);
return 0;
}
}
public static class Handler implements InvocationHandler, Serializable {
private final If original;
public Handler(If original) {
this.original = original;
}
public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
System.out.println("BEFORE");
method.invoke(original, args);
System.out.println("AFTER");
//System.out.println(method);
return null;
}
}
public static void main(String[] args) throws FileNotFoundException, IOException{
/// OutputStream file = null;
Original original = new Original();
Handler handler = new Handler(original);
If f = (If) Proxy.newProxyInstance(If.class.getClassLoader(),new Class[] { If.class },handler);
OutputStream file = new FileOutputStream("quarks.ser");
OutputStream buffer = new BufferedOutputStream(file);
ObjectOutput output = new ObjectOutputStream(buffer);
output.writeObject(handler.invoke(f,handler.original,"a"));
output.close();
}
}
实现此结果的最佳方法是什么,序列化代理对象?
答案 0 :(得分:1)
我们来看看:
output.writeObject(handler.invoke(f,handler.original,"a"));
此处您没有序列化代理f
,而是序列调用的结果:
handler.invoke(f,handler.original,"a")
此方法调用还需要一个参数数组,因此您需要传递数组而不是字符串。
handler.invoke(f,handler.original,new Object[]{"a"})
并且handler.original
不是一种方法......它应该是If.class.getMethods()[0]
handler.invoke(f,If.class.getMethods()[0],new Object[]{"a"})
但是因为它是代表如果它可以写:
f.originalMethod("a")
但是方法返回null:
public Object invoke(Object proxy, Method method, Object[] args) {
// [...]
return null;
}
所以实际上你正在尝试序列化null
,这是没有意义的。
只要处理程序本身可序列化,代理就可以序列化。
public interface Adder {
int add(int x, int y);
}
处理程序必须是Serializable对象
public class AdderHandler implements InvocationHandler, Serializable {
private int factor;
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
int a = (Integer) args[0];
int b = (Integer) args[1];
return (a+b)*factor;
}
public static Adder newInstance(int factor){
Class[] clazz = new Class[]{Adder.class};
AdderHandler h = new AdderHandler(factor);
return (Adder) Proxy.newProxyInstance(AdderHandler.class.getClassLoader(), clazz, h);
}
public AdderHandler(int factor) {
super();
this.factor = factor;
}
}
由于Proxy只有1个字段(处理程序)......
public class TestAdder {
@Test
public void testSerialization() throws Exception {
Adder adder = AdderHandler.newInstance(2);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bos);){
oos.writeObject(adder);
}
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
try(ObjectInputStream ois = new ObjectInputStream(bis);){
Adder adder2 = (Adder) ois.readObject();
int result = adder2.add(1, 3);
assertEquals(8, result);
}
}
}
答案 1 :(得分:0)
您的代码目前正在尝试序列化private final If original
,因为它是Handler
的一部分。但是If
界面不会扩展Serializable
,因此您无法序列化Handler
。你应该改为
interface If extends Serializable
如果不可能,则应使用与Java序列化不同的序列化方法。