Сериализация прокси

Я пытаюсь сериализовать обработчик вызова в файл. Я только пытаюсь сериализовать следующую часть, так как это единственная часть программы, которая изменится:

 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 ответа

Давайте проверим это:

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

Но метод всегда возвращает нуль:

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


}

Ваш код в настоящее время пытается сериализовать private final If original потому что это часть Handler, Тем не менее If интерфейс не расширяется Serializable, так что вы не можете сериализовать Handler, Вы должны либо изменить на

interface If extends Serializable

Или, если это невозможно, следует использовать метод сериализации, отличный от сериализации Java.

Другие вопросы по тегам