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

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

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

>谢谢

解决方法

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

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

这是一个可重用的类,可以包装“任何”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());
    }
}

猜你在找的Java相关文章