Java 通过反序列化创建Springbean
Spring有许多不同的创建bean的方法,但是可以通过反序列化资源来创建bean吗 我的应用程序有许多组件,每个组件都处理特定类型的数据。在测试过程中,数据对象直接实例化并直接在组件上设置,例如component.setData(someDataObject)。在运行时,数据作为序列化对象可用,并由组件从序列化流中读入(该流作为资源从Spring上下文中传入) 与其让每个组件从流中显式地反序列化其数据,不如让Spring从资源中反序列化数据对象并在目标组件上设置它,这样会更加一致和灵活。这样,组件就与它们的数据来源隔离开来 是否有反序列化FactoryBean或类似的东西 编辑: 下面是一些希望澄清的示例代码:Java 通过反序列化创建Springbean,java,spring,serialization,javabeans,Java,Spring,Serialization,Javabeans,Spring有许多不同的创建bean的方法,但是可以通过反序列化资源来创建bean吗 我的应用程序有许多组件,每个组件都处理特定类型的数据。在测试过程中,数据对象直接实例化并直接在组件上设置,例如component.setData(someDataObject)。在运行时,数据作为序列化对象可用,并由组件从序列化流中读入(该流作为资源从Spring上下文中传入) 与其让每个组件从流中显式地反序列化其数据,不如让Spring从资源中反序列化数据对象并在目标组件上设置它,这样会更加一致和灵活。这样,
public class ComponentData implements Externalizable
{
// a complex data structure, behind a simpler interface
}
public class Component
{
private ComponenttData componentData;
public Component(ComponentData data)
{
componentData = data;
}
// other methods that operate using the data
// factory method to create from serialized data
static Component createFromResource(Resource resource)
{
return new Component(deserialize(resource));
}
}
组件有多种类型,每种组件类型都会使用不同的数据实例多次实例化
在测试中,组件及其组件数据仪器是在代码中构造的。在生产中,使用具有“factory method”属性的Springbean来调用静态Componnet.createFromResource方法,该方法对资源中的数据进行反序列化。有许多类型的组件,每个组件都有相同的静态方法来从反序列化数据构造。由于重复,这本身似乎很糟糕。在我看来,测试和生产中的组件构造不一样也很奇怪。如果反序列化可以移动到Spring上下文中,那么可以删除组件上的静态方法,所有依赖项注入都由Spring完成,而不必将其作为特例进行编码
我想象着
<bean name="componentData" class="DeserializingFactoryBean">
<constructor-arg value="/data/componentData1.dat"/> <!-- resource -->
</bean>
<bean name="component" class="Component">
<constructor-arg ref="componentData"/>
</bean>
当我最初发布时,我认为这可能存在,但我认为我可能错过了巨大的SpringJavadocs。从最初的响应来看,Spring似乎没有反序列化工厂bean
如果反序列化的GfactoryBean不是正确的方法,那么有哪些替代方法
是否有反序列化BeanFactory
或类似的东西
从来没有听说过,坦白说,我不希望我的初始化被不透明(对人类而言)的序列化对象控制
但是,如果您真的认为这是一个好主意(嗯哼),那么创建一个自定义的
BeanFactory
就不难了。是的,您可以像done for一样实现自己的BeanFactory。但我不确定,那是你想要的。在应用程序上下文中需要额外的bean。我将实现一个从流中加载bean和/或它们的方法。这是对其他海报的评论。正如他们所指出的,Spring中没有反序列化工厂支持,所以我创建了一个
下面是通过从资源反序列化创建bean的代码。默认情况下,将创建一个实例,并为每次使用返回相同的实例。您可以将属性singleton
设置为false
,每次使用都会反序列化一个新实例
它是这样使用的
<bean name="myBean" class="DeserializingFactoryBean">
<property name="source" value="mybean.ser"/>
<property name="objectType" value="org.acme.MyBean"/>
</bean>
代码呢
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import java.io.BufferedInputStream;
import java.io.ObjectInputStream;
public class DeserializingFactoryBean extends AbstractFactoryBean
{
private Resource source;
private Class<?> objectType;
private int deserializationCount;
public DeserializingFactoryBean()
{
}
public DeserializingFactoryBean(Resource source, Class<?> objectType)
{
this.source = source;
this.objectType = objectType;
}
public void afterPropertiesSet() throws Exception
{
Assert.notNull(objectType, "Property 'objectType' may not be null");
Assert.notNull(source, "Property 'source' may not be null");
super.afterPropertiesSet();
}
public Resource getSource()
{
return source;
}
public void setSource(Resource source)
{
this.source = source;
}
public void setObjectType(Class<?> objectType)
{
this.objectType = objectType;
}
public Class getObjectType()
{
return objectType;
}
@Override
protected Object createInstance() throws Exception
{
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(source.getInputStream()));
Object result = oin.readObject();
if (!objectType.isInstance(result))
throw new ClassCastException(String.format("Deserialized object is not an instance of %s",objectType.getName()));
oin.close();
return result;
}
}
import org.springframework.beans.factory.config.AbstractFactoryBean;
导入org.springframework.core.io.Resource;
导入org.springframework.util.Assert;
导入java.io.BufferedInputStream;
导入java.io.ObjectInputStream;
公共类DeserializengFactoryBean扩展了AbstractFactoryBean
{
私人资源来源;
私有类objectType;
私有int反序列化计数;
public反序列化gfactorybean()
{
}
public DeserializengFactoryBean(资源源,类objectType)
{
this.source=源;
this.objectType=objectType;
}
public void afterPropertieSet()引发异常
{
Assert.notNull(objectType,“属性'objectType'不能为null”);
Assert.notNull(source,“属性‘source’不能为null”);
super.afterPropertiesSet();
}
公共资源getSource()
{
返回源;
}
public void setSource(资源源)
{
this.source=源;
}
public void setObjectType(类objectType)
{
this.objectType=objectType;
}
公共类getObjectType()
{
返回objectType;
}
@凌驾
受保护对象createInstance()引发异常
{
ObjectInputStream oin=新的ObjectInputStream(新的BufferedInputStream(source.getInputStream());
对象结果=oin.readObject();
如果(!objectType.isInstance(结果))
抛出新的ClassCastException(String.format(“反序列化对象不是%s的实例”,objectType.getName());
oin.close();
返回结果;
}
}
序列化类是一个复杂的语言数据块,由复杂而漫长的过程生成。我意识到序列化可能很脆弱,但是,在这种情况下,代码和数据将始终保持一致。数据可以表示为XML或其他(对人类)透明的格式,但我看不出这样做有什么好处——原始数据不是为人眼准备的!尺寸将大大增加。序列化具有有效的用途,因此将其作为bean的源绑定到spring中似乎是有意义的。@mdma-您的用例是一个非常不寻常的用例。不管怎样,一家定制的豆工厂应该能帮你完成这项工作。谢谢你的意见,阿恩。使用BeanFactoryPostProcessor可以在特定情况下很好地工作(例如,根据bean名称从资源中配置每个bean-BeanFactoryPostProcessor配置了从bean名称到资源的映射,类似于Spring MVC中的映射),它确实涉及相当多的连接和约定(例如,使用哪个setter来