序列化代理

时间:2017-07-04 22:54:11

标签: java serialization proxy dynamic-proxy invocationhandler

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

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

}

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

2 个答案:

答案 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序列化不同的序列化方法。