-2

我正在尝试将调用处理程序序列化为文件。我只是试图序列化以下部分,因为它是程序中唯一会改变的部分:

 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();    
}

}

实现此结果的最佳方法是序列化代理对象是什么?

4

2 回答 2

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"})

但由于它是 If 的代理,它可以写成:

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);
}

处理程序必须是可序列化的对象

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;
    }
}

由于代理只有 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);
        }
    }


}
于 2017-07-05T00:15:01.953 回答
0

您的代码当前正在尝试序列化private final If original,因为它是Handler. 但是If接口不扩展Serializable,所以你不能序列化Handler。您应该更改为

interface If extends Serializable

或者,如果这不可能,您应该使用与 Java 序列化不同的序列化方法。

于 2017-07-04T23:44:38.437 回答