我正在使用JAXB从XSD文件创建
Java对象.我正在创建不可变的包装器来隐藏JAXB生成的对象(之前我正在更新JAXB对象来实现不可变接口并返回到客户端,但是意识到改变自动生成的类是不好的,因此使用包装器)
目前,我将这些不可变换的包装器归还给客户端应用程序.是否有任何选项,以便自动生成的类将是不可变的,它将避免创建不可变的包装器的额外工作.鼓励任何其他方法.
>谢谢
解决方法@H_404_8@
您可以在将bean返回给客户端之前为您创建一个代理服务器.您将需要
javassist从类创建代理(直接从Java SE创建来自接口的代理).
这是一个可重用的类,可以包装“任何”POJO的方法:
import java.lang.reflect.Method;
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;
public class Utils {
public static <C> C createInmutableBean(Class<C> clazz,final C instance)
throws InstantiationException,IllegalAccessException {
if (!clazz.isAssignableFrom(instance.getClass())) {
throw new IllegalArgumentException("given instance of class "
+ instance.getClass() + " is not a subclass of " + clazz);
}
ProxyFactory f = new ProxyFactory();
f.setSuperclass(clazz);
f.setFilter(new MethodFilter() {
public boolean isHandled(Method m) {
// ignore finalize()
return !m.getName().equals("finalize");
}
});
Class c = f.createClass();
MethodHandler mi = new MethodHandler() {
public Object invoke(Object self,Method m,Method proceed,Object[] args) throws Throwable {
if (m.getName().startsWith("set")) {
throw new RuntimeException("this bean is inmutable!");
}
return m.invoke(instance,args); // execute the original method
// over the instance
}
};
C proxy = (C) c.newInstance();
((Proxy) proxy).setHandler(mi);
return (C) proxy;
}
}
这里是一个示例代码.让员工成为你的豆子:
public class Employee{
private String name="John";
private String surname="Smith";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
};
这里有一个测试用例,表明您可以为POJO创建一个代理,使用它的getter,但是不能使用它的setter
@Test
public void testProxy() throws InstantiationException,IllegalAccessException{
Employee aBean = new Employee();
//I can modify the bean
aBean.setName("Obi-Wan");
aBean.setSurname("Kenobi");
//create the protected java bean with the generic utility
Employee protectedBean = Utils.createInmutableBean(Employee.class,aBean);
//I can read
System.out.println("Name: "+protectedBean.getName());
System.out.println("Name: "+protectedBean.getSurname());
//but I can't modify
try{
protectedBean.setName("Luke");
protectedBean.setSurname("Skywalker");
throw new RuntimeException("The test should not have reached this line!");
}catch(Exception e){
//I should be here
System.out.println("The exception was expected! The bean should not be modified (exception message: "+e.getMessage()+")");
assertEquals("Obi-Wan",protectedBean.getName());
assertEquals("Kenobi",protectedBean.getSurname());
}
}
这是一个可重用的类,可以包装“任何”POJO的方法:
import java.lang.reflect.Method; import javassist.util.proxy.MethodFilter; import javassist.util.proxy.MethodHandler; import javassist.util.proxy.Proxy; import javassist.util.proxy.ProxyFactory; public class Utils { public static <C> C createInmutableBean(Class<C> clazz,final C instance) throws InstantiationException,IllegalAccessException { if (!clazz.isAssignableFrom(instance.getClass())) { throw new IllegalArgumentException("given instance of class " + instance.getClass() + " is not a subclass of " + clazz); } ProxyFactory f = new ProxyFactory(); f.setSuperclass(clazz); f.setFilter(new MethodFilter() { public boolean isHandled(Method m) { // ignore finalize() return !m.getName().equals("finalize"); } }); Class c = f.createClass(); MethodHandler mi = new MethodHandler() { public Object invoke(Object self,Method m,Method proceed,Object[] args) throws Throwable { if (m.getName().startsWith("set")) { throw new RuntimeException("this bean is inmutable!"); } return m.invoke(instance,args); // execute the original method // over the instance } }; C proxy = (C) c.newInstance(); ((Proxy) proxy).setHandler(mi); return (C) proxy; } }
这里是一个示例代码.让员工成为你的豆子:
public class Employee{ private String name="John"; private String surname="Smith"; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } };
这里有一个测试用例,表明您可以为POJO创建一个代理,使用它的getter,但是不能使用它的setter
@Test public void testProxy() throws InstantiationException,IllegalAccessException{ Employee aBean = new Employee(); //I can modify the bean aBean.setName("Obi-Wan"); aBean.setSurname("Kenobi"); //create the protected java bean with the generic utility Employee protectedBean = Utils.createInmutableBean(Employee.class,aBean); //I can read System.out.println("Name: "+protectedBean.getName()); System.out.println("Name: "+protectedBean.getSurname()); //but I can't modify try{ protectedBean.setName("Luke"); protectedBean.setSurname("Skywalker"); throw new RuntimeException("The test should not have reached this line!"); }catch(Exception e){ //I should be here System.out.println("The exception was expected! The bean should not be modified (exception message: "+e.getMessage()+")"); assertEquals("Obi-Wan",protectedBean.getName()); assertEquals("Kenobi",protectedBean.getSurname()); } }