Spring有许多不同的创建bean的方法,但是可以通过反序列化资源来创建bean吗?
我的应用程序有许多组件,每个组件都操纵某种类型的数据。在测试期间,数据对象被直接实例化并直接设置在组件上,例如, component.setData(someDataObject)。在运行时,数据可作为序列化对象使用,并由组件从序列化流中读取(流作为Spring上下文中的资源传入。)
不是让每个组件从流中显式地反序列化它的数据,而是让Spring从资源反序列化数据对象并将其设置在目标组件上更加一致和灵活。这样,组件就会与数据的来源隔离开来。
是否有DeserializerFactoryBean或类似的东西?
编辑:
以下是一些希望澄清的示例代码:
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));
}
}
有许多类型的组件,每种组件类型使用不同的数据实例多次即时。
在测试中,组件及其ComponentData实例是用代码构造的。在生产中,具有“factory-method”属性的spring-bean用于调用静态Componnet.createFromResource方法,该方法对资源中的数据进行反序列化。有许多类型的组件,每个组件都有相同的静态方法来构建反序列化数据。由于重复,这本身似乎很糟糕。对我来说,测试和生产中的组件构造不一样,这似乎也很奇怪。如果可以将反序列化移动到Spring上下文中,则可以删除组件上的静态方法,然后由Spring完成所有依赖注入,而不必将其作为特殊情况进行编码。
E.g。我想像
这样的东西<bean name="componentData" class="DeserializingFactoryBean">
<constructor-arg value="/data/componentData1.dat"/> <!-- resource -->
</bean>
<bean name="component" class="Component">
<constructor-arg ref="componentData"/>
</bean>
当我最初发布时,我认为这可能存在,但我可能在广阔的春天javadocs中错过了。从初始响应看来,Spring没有反序列化工厂bean。
如果DeserializingFactoryBean不是正确的方法,那么存在哪些替代方案?
答案 0 :(得分:0)
是否有
DeserializerBeanFactory
或类似的东西?
从未听说过一个,坦率地说,我不希望我的初始化由不透明(仅仅是人类)序列化对象控制。
但如果你真的认为这是一个好主意(咳咳),创建一个以这种方式工作的自定义BeanFactory
应该不难。
答案 1 :(得分:0)
是的,您可以为SimpleJndiBeanFactory
实现自己的Beanfactory。但我不确定,这就是你想要的。您需要在应用程序上下文中使用其他bean。我会实现BeanFactoryPostProcessor
加载来自流的bean以及autowire或register。
答案 2 :(得分:0)
这是其他海报的评论。正如他们所指出的那样,Spring中没有反序列化工厂支持,所以我创建了一个。
下面是通过反序列化从资源创建bean的FactoryBean的代码。默认情况下,会创建一个实例,并为每次使用返回相同的实例。您可以将属性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;
}
}