是否有标准或简单的方法来冻结JavaBean?

时间:2012-10-20 00:31:15

标签: java javabeans

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

我没有能力为每个bean编写Mutable / Immutable版本,也没有自定义Jackson工厂,因此我正在寻找类似于Collections.unmodifiableCollection(...);的库或函数调用,但是对于bean来说。 / p>

(是的,我知道如果原始的bean被泄露,那么真的冻结了它。但是我会在创建之后立即包装或冻结它们,而不再使用原件。)

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

当我搜索“java beans jackson immutable”时,谷歌发现了这个:

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

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

答案 1 :(得分:2)

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

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

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

如果它们是pojo,你应该能够使用像javassist或cglib这样的库来创建一个增强版本,其中你的setter被存根以引发异常。

这是一个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;

}

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