Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有标准或简单的方法来冻结JavaBean?_Java_Javabeans - Fatal编程技术网

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

有没有标准或简单的方法来冻结JavaBean?,java,javabeans,Java,Javabeans,我发现自己不幸地使用了大量JavaBeans。我说不幸是因为我不喜欢它们是可变的。因此,在我创建bean之后(我使用Jackson将它们从JSON转换过来),我希望在指定的时刻“冻结”bean,以确保它们不会发生突变 我没有能力编写每个bean的可变/不可变版本,也没有能力编写定制的Jackson工厂,所以我正在寻找一个库或函数调用,就像Collections.unmodifiableCollection(…)但是对于bean (是的,我知道如果原版的bean被泄露,这并不是真正的冻结。但我会在

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

我没有能力编写每个bean的可变/不可变版本,也没有能力编写定制的Jackson工厂,所以我正在寻找一个库或函数调用,就像
Collections.unmodifiableCollection(…)但是对于bean

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


有什么想法吗?

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


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

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

public class ImmutableBean {
    public static <T> T makeImmutable(T t) { ... }
}
公共类ImmutableBean{
公共静态T使不可变(T T){…}
}
然后,您可以创建一个java.lang.Proxy实例,该实例或者特定于您的bean,或者查找类似于以“set”开头的方法的模式,并抛出一些特定的异常。下面是一个关于创建代理实例的很好的简短教程:

如果它们是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;

}
public static T makeImmutable(final T)抛出NotFoundException、InstanceionException、IllegaAccessException{
MethodHandler mh=新MethodHandler(){
@凌驾
公共对象调用(java.lang.Object self、java.lang.reflect.Method thisMethod、java.lang.reflect.Method procedue、java.lang.Object[]args)抛出Throwable{
if(thisMethod.getName().startsWith(“set”)){
抛出新的UnsupportedOperationException();
}
返回procedure.invoke(t,args);
}
};
ProxyFactory ProxyFactory=新的ProxyFactory();
setSuperclass(t.getClass());
类clazz=(类)proxyFactory.createClass();
T instance=clazz.newInstance();
((ProxyObject)实例).setHandler(mh);
返回实例;
}

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

请问您为什么要执行此操作?用例场景是什么?如前所述,我正在解析JSON->JavaBeans(许多不同的类型)。解析之后,我希望确保它们是可以在系统中传递的不可变数据对象。我不喜欢使用不使用setter的“约定”,因为最终有人会忘记“约定”。所以我希望确保它们是不可变的。+1,回答这个问题会非常有用,但没有setter,Jackson无法创建bean。我正在寻找一种解决方案,无需编写自定义解析器/转换器即可实现这一点,因为我的系统中有很多bean类型。如果您使用的构造函数具有所有属性,则不需要设置器。如果您想要一个可变对象,则仍然需要设置器。有必要,但还不够。很好!其中有几个会很好地工作。可惜的是,我的谷歌搜索中没有出现这种情况——我太专注于冷冻,因为我认为必须要有冷冻setters@AdamVandenberg-只有当框架了解如何内省并使用带参数的构造函数时,这才有效。还有一个基本问题是如何在命名属性和构造函数参数之间映射。。。基于通过Java反射提供的信息。