2010-04-27 140 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