1

実験として、「load」を介して Hibernate エンティティ pojo を取得し、通常のシリアル化を介してファイルに書き込みました。通常の逆シリアル化によって別のプログラムでそのファイルを再度読み取り、リフレクションを使用して、エンティティ オブジェクトのプロキシ クラスに含まれるフィールドとメソッドを見つけました。

驚いたのは、プロキシ クラスに含まれるすべてのメソッドが表示されたことです (たとえば、'getHibernateLazyInitializer()' または 'CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[])' など)。

さらに、デシリアライズされたインスタンスで「getHibernateLazyInitializer()」メソッドを呼び出すことができました。さて、プロキシ コードが動的に生成され、そのクラスが作成された JVM がシャットダウンした後にそのクラスが存在しない場合、どうすればそのメソッドを呼び出すことができたのでしょうか? メソッドバイトコードも、プロキシを介して Hibernate pojo 用にシリアライズ/デシリアライズされますか?

4

3 に答える 3

0

いいえ、そうではありません。また、クラスパスがそのクラスを認識していないJavaプロセスでオブジェクトを逆シリアル化しようとすると、エラーが発生します。

于 2012-04-05T07:36:01.980 に答える
0

実際にシリアル化したオブジェクト インスタンスは、エンティティ クラス自体ではなく、そのクラスを拡張するプロキシであるため、逆シリアル化すると、エンティティ インスタンスではなくプロキシが返されることは明らかです。

于 2012-04-05T07:44:59.673 に答える
0

OK、さらにデバッグしたところ、プロキシされたインスタンスをシリアライズしているときに、Hibernate が実際に SerializableProxy のインスタンスを書き込むことがわかりました。これは、プロキシ クラスが、前述の SerializableProxy インスタンスを返す「writeReplace()」メソッドを持つインターフェイス「HibernateProxy」を実装しているために発生します。

このインスタンスがデシリアライズされると、SerializableProxy の readResolve() が開始され、SerializableProxy インスタンスに記載されている情報に基づいて作成され、CGLib Enhancer を順番に使用する HibernateProxy オブジェクトが返されます。そのため、これらすべてのメソッドを確認して呼び出すこともできました。

結論: ストリームにはメソッド コードが書き込まれていません。Hibernate は writeReplace によってオブジェクト自体を変更し、そのオブジェクトが読み戻されるときに readResolve と CGLIb を使用してプロキシを再作成します。

于 2012-04-05T09:12:26.817 に答える