, wie Singleton-Spring-Beans nach der Deserialisierung wieder anhängen

8

Ich möchte Singleton-abhängige Abhängigkeiten nach der Deserialisierung in Spring Beans des Prototyps reinject.

Angenommen, ich habe eine Process-Bean, die von einer Repository-Bean abhängt. Die Repository-Bean ist ein Bereich wie ein Singleton, aber die Process-Bean ist ein Prototyp-Bereich. Periodisch serialisiere ich den Prozess und deserialisiere ihn später.

%Vor%

Ich möchte das Repository nicht serialisieren und deserialisieren. Ich möchte auch nicht "transient" auf die Membervariable setzen, die in Process einen Verweis darauf enthält, noch einen Verweis auf irgendeine Art von Proxy oder etwas anderes als eine einfache alte Membervariable, die als Repository deklariert ist.

Was ich denke, ist, dass der Prozess seine Abhängigkeit mit einem serialisierbaren Proxy gefüllt hat, der (mit einer vorübergehenden Referenz) auf das Repository zeigt und das Repository bei der Deserialisierung wieder findet. Wie könnte ich Spring dazu anpassen?

Ich denke, ich könnte einen Proxy verwenden, um die Abhängigkeitsreferenzen zu halten, ähnlich. Ich wünschte, ich könnte diese genaue Technik anwenden. Aber der Proxy, den ich gesehen habe Spring ist nicht serialisierbar, und die Dokumente sagen, dass, wenn ich es mit einer Singleton-Bean verwende, ich eine Ausnahme bekomme.

Ich könnte vielleicht einen benutzerdefinierten Bereich für die Singleton-Beans verwenden, der immer einen Proxy liefert, wenn er nach einer benutzerdefinierten Bean gefragt wird. Ist das eine gute Idee? Andere Ideen?

    
Ladlestein 12.08.2010, 20:38
quelle

5 Antworten

1

Wie wäre es, wenn Sie Aspekte hinzugefügt haben, um einen Injektionsschritt hinzuzufügen, wenn Sie das Objekt deserialisieren?

Sie würden dafür AspectJ oder ähnliches benötigen. Es würde sehr ähnlich der @Configurable-Funktion in Spring funktionieren.

z.B. Fügen Sie einen Rat hinzu, um die Methode "private void readObject (ObjectInputStream in) löst IOException, ClassNotFoundException"

Dieser Artikel kann auch helfen: Ссылка

    
Pablojim 12.08.2010, 21:48
quelle
3

Ich habe das stattdessen ohne Proxy verwendet:

%Vor%

Das Beispiel bezieht sich auf eine Web-Umgebung, wenn der Anwendungsserver die Sitzung serialisiert, aber sie sollte für jeden ApplicationContext funktionieren.

    
nlebas 14.09.2011 01:37
quelle
3

Spring bietet eine Lösung für dieses Problem.

Sehen Sie sich die Frühjahrsdokumentation an Ссылка .

  

7.8.1 Verwendung von AspectJ zur Abhängigkeitsinjektion von Domänenobjekten mit Spring

     

...

     

Die Unterstützung ist für Objekte gedacht, die außerhalb erstellt werden   der Kontrolle eines Containers. Domänenobjekte fallen oft in   diese Kategorie, weil sie oft programmgesteuert erstellt werden   Verwenden des neuen Operators oder eines ORM-Tools als Ergebnis einer Datenbankabfrage.

Der Trick besteht darin, Ladezeitweben zu verwenden. Starten Sie einfach den jvm mit -javaagent: pfad / zu / org.springframework.instrument- {version} .jar. Dieser Agent erkennt jedes Objekt, das instanziiert wird, und wenn es mit @Configurable annotiert wird, konfiguriert es (inject @Autowired oder @Resource-Abhängigkeiten) dieses Objekt.

Ändern Sie einfach die Process-Klasse in

%Vor%

Immer wenn Sie eine neue Instanz erstellen

%Vor%

spring wird automatisch die Abhängigkeiten injizieren. Dies funktioniert auch, wenn das Process-Objekt deserialisiert wird.

    
René Link 07.02.2012 20:44
quelle
1

Ich denke, die Idee, eine Bean zu serialisieren und dann eine Neuinjektion von Abhängigkeiten zu erzwingen, ist nicht die beste Architektur.

Wie wäre es mit einer Art ProcessWrapper Bean, die ein Singleton sein könnte? Es würde mit dem Repository injiziert und verwaltet entweder die Deserialisierung des Prozesses oder hat einen Setter dafür. Wenn ein neuer Prozess im Wrapper festgelegt wird, würde er setRepository() für den Prozess aufrufen. Die Beans, die den Prozess verwenden, können entweder vom Wrapper mit dem neuen Beer gesetzt werden oder den ProcessWrapper aufrufen, der an den Prozess delegiert wird.

%Vor%     
Gray 12.08.2010 21:03
quelle
0

Beantworten meiner eigenen Frage: Wie ich das Problem bisher gelöst habe, ist eine Basisklasse zu erstellen, die serialisiert und deserialisiert mit einem billigen kleinen Proxy. Der Proxy enthält nur den Namen der Bean.

Sie werden feststellen, dass es einen globalen Zugriff auf den Spring-Kontext verwendet. Eine elegantere Lösung könnte den Kontext in einer thread-lokalen Variablen speichern, etwa so.

%Vor%

Das resultierende serialisierte Objekt ist 150 Bytes oder so (wenn ich mich richtig erinnere).

    
Ladlestein 29.09.2010 18:39
quelle