2010-08-12 72 views
8

我想在它們被反序列化之後,將singleton範圍的依賴關係重新注入原型Spring bean。如何在反序列化時重新附加singleton Spring bean

說我有一個Process bean,它依賴於一個Repository bean。 Repository bean的作用範圍是一個singleton,但Process bean是原型範圍的。我會定期序列化進程,然後將其反序列化。

class Process { 
    private Repository repository; 
    // getters, setters, etc. 
} 

我不想序列化和反序列化存儲庫。我也不希望將「transient」放在Process中引用它的成員變量上,也不要對某種代理的引用,或者將其聲明爲Repository的普通舊成員變量以外的任何其他引用。

我想我想要的是讓Process依賴於一個可序列化的代理,該代理指向Repository,並且在反序列化時可以再次找到Repository。我如何定製Spring來做到這一點?

我想我可以使用代理來保存依賴關係引用,很像。我希望我可以使用這種確切的技術。但是我看到Spring生成的代理不是可序列化的,文檔說如果我將它與singleton bean一起使用,我會得到一個異常。

我可以在singleton bean上使用自定義作用域,它在請求自定義作用域bean時總是會提供代理。這是一個好主意嗎?其他想法?

+0

這些bean在哪些應用程序上下文中?一個webapp上下文? – skaffman 2010-08-12 21:00:23

+0

現在,不是一個webapp上下文。稍後,可能會是一個webapp上下文。 – Ladlestein 2010-08-12 21:47:21

+0

在這種情況下,上下文是如何引導的?它是一個桌面應用程序嗎? – skaffman 2010-08-12 22:02:46

回答

1

如何在反序列化對象時使用方面添加註入步驟?

你需要AspectJ或類似的。它和Spring的@Configurable函數非常相似。

例如周圍的一個補充一些建議「私人無效的readObject(ObjectInputStream中的)拋出IOException異常,ClassNotFoundException的」方法

本文還可以幫助:http://java.sun.com/developer/technicalArticles/Programming/serialization/

+0

我一直在抵制方面,因爲我不想在這裏搖擺船,如果你知道我的意思,但這是一個探索性項目,所以也許現在是時候了。 不過,我想知道其他方法來做到這一點。 – Ladlestein 2010-08-13 00:33:21

1

我認爲序列化bean然後強制重新依賴的想法並不是最好的體系結構。

如何擁有某種類型的ProcessWrapper bean,而不是可能是單例。它將被注入Repository並管理Process的反序列化或者爲它設置一個setter。在包裝器中設置新進程時,它將在進程上調用setRepository()。使用Process的bean可以由包裝器用新的bean設置,也可以調用將委託給Process的ProcessWrapper。

class ProcessWrapper { 
    private Repository repository; 
    private Process process; 
    // getters, setters, etc. 

    public void do() { 
     process.do(); 
    } 

    public void setProcess(Process process) { 
     this.process = process; 
     this.process.setRepository(repository); 
    } 
} 
+0

但是'RepositoryFactory'將如何工作?它必須是可序列化的,因此不能引用應用程序上下文。它只是推動了這個問題。 – skaffman 2010-08-12 21:10:35

+0

對不起,對。我大量編輯了我的回覆。 – Gray 2010-08-13 13:07:20

+0

過程和存儲庫僅僅是一個例子(和過程是一個不好的例子;對此感到抱歉)。一般來說,被反序列化的bean是控制器,用於管理用戶和我們的webapp之間的特定交互。其中有很多,而且總是有更多的要寫。他們消耗許多不同的服務。 – Ladlestein 2010-08-14 01:57:33

0

回答我的問題:我是如何解決這個問題至今創建一個使用便宜的小代理序列化和反序列化的基類。代理只包含bean的名稱。

你會注意到它使用全局來訪問Spring上下文;一個更優雅的解決方案可能會將上下文存儲在一個線程局部變量中,就像那樣。

public abstract class CheaplySerializableBase 
    implements Serializable, BeanNameAware { 

    private String name; 

    private static class SerializationProxy implements Serializable { 

     private final String name; 

     public SerializationProxy(CheaplySerializableBase target) { 
      this.name = target.name; 
     } 

     Object readResolve() throws ObjectStreamException { 
      return ContextLoader.globalEvilSpringContext.getBean(name); 
     } 

    } 

    @Override 
    public void setBeanName(String name) { 
     this.name = name; 
    } 

    protected Object writeReplace() throws ObjectStreamException { 
     if (name != null) { 
      return new SerializationProxy(this); 
     } 
     return this; 
    } 
} 

生成的序列化對象是150個字節左右(如果我沒記錯的話)。

3

我用這個來代替,無需任何代理:

public class Process implements HttpSessionActivationListener { 
    ... 
    @Override 
    public void sessionDidActivate(HttpSessionEvent e) { 
     ServletContext sc = e.getSession().getServletContext(); 
     WebApplicationContext newContext = WebApplicationContextUtils 
      .getRequiredWebApplicationContext(sc); 
     newContext.getAutowireCapableBeanFactory().configureBean(this, beanName); 
    } 
} 

的例子是針對網絡環境時,應用服務器序列化的會話,但它應該對任何的ApplicationContext工作。

3

Spring爲這個問題提供了一個解決方案。

看看春季文檔http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-atconfigurable

7.8.1使用AspectJ來注入域對象與Spring

...

的支持旨在用於以外的任何容器的控制 創建的對象。域對象通常屬於 這一類別,因爲它們通常是使用新運算符或ORM工具以編程方式創建的 作爲數據庫查詢的結果。

訣竅是使用加載時間編織。只需使用-javaagent:path/to/org.springframework.instrument- {version} .jar啓動jvm。該代理將識別每個實例化的對象,如果它使用@Configurable進行註釋,它將配置(注入@Autowired或@Resource依賴項)該對象。當你創建一個新的實例

Process process = new Process(); 

春天將自動注入依賴

只要改變工藝類

@Configurable 
class Process { 

    @Autowired 
    private transient Repository repository; 
    // getters, setters, etc. 
} 

。 如果Process對象被反序列化,這也適用。

+0

爲什麼不將'transient'關鍵字添加到資源庫成員變量中?否則,您的Repository類需要可序列化。 ,但我不明白你爲什麼想序列化它。 – herman 2012-11-14 16:18:05