java – 使用JAXB创建不可变对象

前端之家收集整理的这篇文章主要介绍了java – 使用JAXB创建不可变对象前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用JAXB从XSD文件创建 Java对象.我正在创建不可变的包装器来隐藏JAXB生成的对象(之前我正在更新JAXB对象来实现不可变接口并返回到客户端,但是意识到改变自动生成的类是不好的,因此使用包装器)

目前,我将这些不可变换的包装器归还给客户端应用程序.是否有任何选项,以便自动生成的类将是不可变的,它将避免创建不可变的包装器的额外工作.鼓励任何其他方法.

>谢谢

解决方法

您可以在将bean返回给客户端之前为您创建一个代理服务器.您将需要 javassist从类创建代理(直接从Java SE创建来自接口的代理).

然后,如果调用以“set”开头的方法,则可以抛出异常.

这是一个可重用的类,可以包装“任何”POJO的方法

  1. import java.lang.reflect.Method;
  2.  
  3. import javassist.util.proxy.MethodFilter;
  4. import javassist.util.proxy.MethodHandler;
  5. import javassist.util.proxy.Proxy;
  6. import javassist.util.proxy.ProxyFactory;
  7.  
  8. public class Utils {
  9.  
  10. public static <C> C createInmutableBean(Class<C> clazz,final C instance)
  11. throws InstantiationException,IllegalAccessException {
  12. if (!clazz.isAssignableFrom(instance.getClass())) {
  13. throw new IllegalArgumentException("given instance of class "
  14. + instance.getClass() + " is not a subclass of " + clazz);
  15. }
  16. ProxyFactory f = new ProxyFactory();
  17. f.setSuperclass(clazz);
  18. f.setFilter(new MethodFilter() {
  19. public boolean isHandled(Method m) {
  20. // ignore finalize()
  21. return !m.getName().equals("finalize");
  22. }
  23. });
  24. Class c = f.createClass();
  25. MethodHandler mi = new MethodHandler() {
  26. public Object invoke(Object self,Method m,Method proceed,Object[] args) throws Throwable {
  27. if (m.getName().startsWith("set")) {
  28. throw new RuntimeException("this bean is inmutable!");
  29. }
  30.  
  31. return m.invoke(instance,args); // execute the original method
  32. // over the instance
  33. }
  34. };
  35. C proxy = (C) c.newInstance();
  36.  
  37. ((Proxy) proxy).setHandler(mi);
  38. return (C) proxy;
  39. }
  40. }

这里是一个示例代码.让员工成为你的豆子:

  1. public class Employee{
  2. private String name="John";
  3. private String surname="Smith";
  4. public String getName() {
  5. return name;
  6. }
  7. public void setName(String name) {
  8. this.name = name;
  9. }
  10. public String getSurname() {
  11. return surname;
  12. }
  13. public void setSurname(String surname) {
  14. this.surname = surname;
  15. }
  16. };

这里有一个测试用例,表明您可以为POJO创建一个代理,使用它的getter,但是不能使用它的setter

  1. @Test
  2. public void testProxy() throws InstantiationException,IllegalAccessException{
  3. Employee aBean = new Employee();
  4.  
  5. //I can modify the bean
  6. aBean.setName("Obi-Wan");
  7. aBean.setSurname("Kenobi");
  8.  
  9. //create the protected java bean with the generic utility
  10. Employee protectedBean = Utils.createInmutableBean(Employee.class,aBean);
  11.  
  12. //I can read
  13. System.out.println("Name: "+protectedBean.getName());
  14. System.out.println("Name: "+protectedBean.getSurname());
  15.  
  16. //but I can't modify
  17. try{
  18. protectedBean.setName("Luke");
  19. protectedBean.setSurname("Skywalker");
  20. throw new RuntimeException("The test should not have reached this line!");
  21. }catch(Exception e){
  22. //I should be here
  23. System.out.println("The exception was expected! The bean should not be modified (exception message: "+e.getMessage()+")");
  24. assertEquals("Obi-Wan",protectedBean.getName());
  25. assertEquals("Kenobi",protectedBean.getSurname());
  26. }
  27. }

猜你在找的Java相关文章