5

我发现自己处于使用大量 JavaBeans 的不幸境地。我说不幸是因为我不喜欢它们是可变的。因此,在创建 bean 之后(我使用 Jackson 将它们从 JSON 转换),我想在指定的时刻“冻结”这些 bean,以确保它们不会发生突变。

我没有能力编写每个 bean 的可变/不可变版本,也没有自定义杰克逊工厂,所以我正在寻找一个库或函数调用,就像Collections.unmodifiableCollection(...);bean 一样。

(是的,我知道如果原始 bean 泄漏,这并没有真正冻结它。但是我会在创建后立即将它们包装或冻结,并且不再使用原始 bean。)

有任何想法吗?

4

2 回答 2

3

当我搜索“java beans jackson immutable”时,Google 发现了这一点:

http://www.cowtowncoder.com/blog/archives/2010/08/entry_409.html

我不知道它是否有效,但文章声称能够做到。

于 2012-10-20T00:58:26.677 回答
3

你是基于 bean 接口还是 pojos ?如果它们是基于接口的,您可以简单地编写一个实用方法:

public class ImmutableBean {
    public static <T> T makeImmutable(T t) { ... }
}

然后,您可以创建一个 java.lang.Proxy 实例,该实例要么特定于您的 bean,要么查找诸如以“set”开头的方法之类的模式,并抛出一些特定的异常。这是一个关于创建代理实例的简短教程: http ://www.javalobby.org/java/forums/t18631.html

如果它们是 pojo 的,您应该能够使用 javassist 或 cglib 之类的库来创建一个增强版本,在该版本中您的设置器被存根以抛出异常。

这是一个 javassist 示例:

 public static <T> T makeImmutable(final T t) throws NotFoundException, InstantiationException, IllegalAccessException {
    MethodHandler mh = new MethodHandler() {
        @Override
        public Object invoke(java.lang.Object self, java.lang.reflect.Method thisMethod, java.lang.reflect.Method proceed, java.lang.Object[] args) throws Throwable {
            if (thisMethod.getName().startsWith("set")) {
                throw new UnsupportedOperationException();
            }
            return proceed.invoke(t, args);
        }

    };

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.setSuperclass(t.getClass());
    Class<T> clazz = (Class<T>) proxyFactory.createClass();
    T instance = clazz.newInstance();
    ((ProxyObject)instance).setHandler(mh);

    return instance;

}

但是,这确实需要您的原始类具有无参数构造函数,因此如果您没有无参数构造函数,您可能必须为您的类执行特定方法。

于 2012-10-20T01:16:57.200 回答