使用JAXB创建不可变对象 [英] Creating immutable objects using JAXB

查看:93
本文介绍了使用JAXB创建不可变对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JAXB从XSD文件创建Java对象。我正在创建不可变的包装器来隐藏由JAXB生成的对象(之前我正在更新JAXB对象以实现不可变的接口并将接口返回到客户端。但是意识到改变自动生成的类是不好的,因此使用包装器)

I am using JAXB to create Java objects from XSD file. I am creating immutable wrappers to conceal objects generated by JAXB (earlier I was updating JAXB objects to implement immutable interface and return interface to client. But realised it is bad to change auto generated classes, hence using wrappers)

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

Currently I am returning these immutable wrappers to client app. Is there any option so that auto generated classes will be immutable and it will avoid extra work of creating immutable wrappers. Any other approach is encouraged.


  • 谢谢

推荐答案

您可以在将bean返回给客户端之前为其创建代理。您需要 javassist 从类创建代理(从中创建代理)接口可以直接使用Java SE完成。

You can create a Proxy for your beans just before returning them to the client. You will need javassist to create Proxies from classes (create proxies from interfaces can be done with Java SE directly).

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

Then, you can throw an exception if methods starting with "set" are invoked.

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

Here is a reusable class with a method that can wrap "any" 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;
 }
}

这是一个示例代码。让Employee成为你的bean:

And here is an example code. Let Employee be your bean:

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

And here a test case showing that you can create a proxy for a POJO, use its getters, but you can't use its setters

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

这篇关于使用JAXB创建不可变对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆