2010-04-27 48 views
1

Spring有许多不同的创建bean的方法,但是可以通过反序列化资源来创建bean吗?通过反序列化创建Spring 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)); 
    } 
} 

有许多类型的组分,和每种组件类型与不同的数据实例instantated数次。

在测试中,组件和它们的ComponentData实例在代码中构造。在生产中,使用具有“工厂方法”属性的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> 

当我最初发布,我认为这可能存在,但我认为我可以在广阔的春天的javadoc错过英寸从最初的回应看来,Spring并没有反序列化的工厂bean。

如果DeserializingFactoryBean是不正确的做法,有什么替代品存在吗?

回答

0

这就是其他海报的评论。正如他们指出的那样,Spring中没有反序列化工厂支持,所以我创建了一个。

以下是FactoryBean的代码,它通过反序列化从资源创建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; 
    } 
} 
0

有没有DeserializerBeanFactory或类似的东西?

从来没有听说过一个,坦率地说我不希望我的初始化由不透明(仅仅是人类)序列化对象控制。

但如果你真的认为这是一个好主意(啊哈),它不应该是很难创建一个自定义BeanFactory奏效的方式。

+0

序列化类是由一个复杂和漫长的过程生成的语言数据的复团块。我意识到序列化可能是脆弱的,但是,在这种情况下,代码和数据将始终保持一致。数据可以表示为XML或其他透明(对人类)格式,但我没有看到我通过这样做获得了什么 - 原始数据不适用于人眼!尺寸会大大增加。 序列化具有有效的用途,所以它能够将它作为bean的源代码与spring联系起来似乎是有意义的。 – mdma 2010-04-27 12:18:14

+0

@mdma - 你是一个非常不寻常的用例。无论如何,一个自定义的BeanFactory应该为你完成这项工作。 – 2010-04-27 13:22:57

0

是的,你可以像做了SimpleJndiBeanFactory实现自己的BeanFactory。但我不确定,那是你想要的。您在应用程序上下文中需要额外的bean。我会实现一个BeanFactoryPostProcessor从流中加载beans,并且它们是autowireregister

+0

感谢您的输入,Arne。在特定情况下使用BeanFactoryPostProcessor可以很好地工作(例如,根据bean名称配置每个bean的资源 - BeanFactoryPostProcessor配置了从bean名称到资源的映射,类似于Spring MVC中的映射),但确实包含一个公平的位(比如哪个setter用来设置数据对象)。我更喜欢一个简单的FactoryBean实现,它配置了一个反序列化资源,它是简单的,通用的和可测试的,并且允许使用数据的bean在通常的方式。 – mdma 2010-04-27 13:33:02