Сериализация прокси
Я пытаюсь сериализовать обработчик вызова в файл. Я только пытаюсь сериализовать следующую часть, так как это единственная часть программы, которая изменится:
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.