動的プロキシをシリアライズする具体的方法

Javassistを使った動的プロキシの作成」エントリと「替わりのオブジェクトをシリアライズするwriteReplace()/readResolve()」エントリを組み合わせると,実行時にその場で作った動的プロキシクラスを元にnewしたインスタンスをシリアライズし,異なるJavaVMプロセスにてデシリアライズできるようになる。今回はその具体的な方法を紹介しよう。

まずは,動的プロキシの対象となる抽象クラスを以下とする。これは「Javassistを使った動的プロキシの作成」で取り上げたものと同一である。

このクラスはabstractなため,当然そのままではnewできない。そこで,動的プロキシクラスの登場である。onClick()メソッドの実装として,output()メソッドを呼び出すだけの実装コードを持つ動的プロキシクラスの生成処理が以下である。

動的プロキシクラスの生成処理を,ProxyFactory#createClass()メソッドに定義しているコードである。createClass()メソッドには,動的プロキシのクラス名を指定できるようにしている。onClick()メソッドのオーバーライドだけでなく,writeReplace()メソッドに関しても,動的プロキシクラスに追加しているのが見てとれるだろう。writeReplace()メソッド内では,シリアライズ対象となる自分自身が持つフィールドの値を(transient修飾子が付けられたもの以外に対して)取得し,フィールド名と値の組み合わせを持つコレクションを作成している。これと,createClass()メソッドの引数で受け取った動的プロキシのクラス名を引数に渡して,SeriarlizedObjectオブジェクトを生成し,そのオブジェクトを替わりのシリアライズ対象として返却している。

SerializedObjectクラスは,コレクションとクラス名を持つ単純なクラスではあるが,readResolve()メソッドを持っていることが特徴的である。

readResolve()メソッドでは,保持しておいたクラス名を元に動的プロキシクラスを生成し,そのインスタンスも生成する。そして保持しておいたフィールドの値を1つずつ生成したインスタンスにセットし,そのインスタンスをデシリアライズ結果として返却している。

ほとんどの例外処理をすっとばしたコードなので,そのままではコンパイルエラーとなるが,本質的な処理は以上である。あとは,以下のように,

として実行結果「0」を得てJavaVMを一旦終了し,次に,

としてあげれば,実行結果「1」を得ることができるだろう。Javassistによって生成した動的プロキシに関しても,writeReplace()/readResolve()メソッドの機構をうまく利用することで,シリアライズが実現可能になることを上記の例は示してくれている。

DIコンテナの普及のおかげで,動的プロキシの生成を自前で行う機会はそう多くないかもしれない。しかし,動的プロキシによって実現できることは多岐に渡るため,知ってるのと知らないのとでは雲泥の差がある。もちろん「ご利用は計画的に」なのは言うまでもないが。。

Trackback URL:

コメントを残す

コメントを投稿するにはログインしてください。

Get Adobe Flash playerPlugin by wpburn.com wordpress themes