web-dev-qa-db-ja.com

リフレクションを介してメソッドの動作を変更する方法は?

いくつかのレガシーコードに静的メソッドがあり、複数のクライアントから呼び出されます。明らかに、それをオーバーライドしたり、依存性注入によって動作を変更したりするオプションはありません。既存のクラスを変更することはできません。

ここでやりたいことは、リフレクションを使用して動作を変更することです(そのメソッド-同じシグネチャと戻り値の型を使用)。

出来ますか ?そうでない場合、どんなデザインパターンでも助けてくれますか?

ありがとう!

編集:何を変更/変更できるかについて、いくつかの混乱があります。既存のクラス/メソッドを変更することはできませんが、プロジェクトにさらにクラスを追加できます。既存のクラスでできることは、それらに注釈を付けることです。これはすべて、既存のコードで何かを壊さないようにするために行われます。つまり、大規模なプロジェクトの完全なテストを意味します。

EDIT 2:Java.lang.InstrumentationはAndroid-またはそれ以外の場合は適切に聞こえます!

25
Jaguar

奇妙な要件のように聞こえます...

とにかく、リフレクションではコードの振る舞いを変更することはできません。現在のコードの探索、メソッドとコンストラクターの呼び出し、フィールド値の変更などができます。

メソッドの動作を実際に変更する場合は、ASMなどのバイトコード操作ライブラリを使用する必要があります。しかし、これは非常に簡単ではなく、おそらく良い考えではありません...

あなたを助けるかもしれないパターン:

  • クラスが最終クラスではなく、クライアントを変更できる場合は、既存のクラスを拡張し、目的の動作でメソッドをオーバーロードします。編集:メソッドが静的でない場合にのみ機能します!
  • アスペクトプログラミング:AspectJを使用してメソッドにインターセプターを追加します

とにかく、最も論理的なことは、既存のクラスを変更する方法を見つけることです。回避策は、コードをより複雑にし、維持するのを難しくします。

幸運を。

27
Pierre Henry

メソッドredefineClasses(ClassDefintion classDefinition)を持つ Instrumentation classを見ることができると思います。

再定義により、メソッド本体、定数プール、および属性が変更される場合があります。再定義では、フィールドやメソッドの追加、削除、名前の変更、メソッドのシグネチャの変更、継承の変更を行ってはなりません。

お役に立てれば。

参照: Javadoc

15
Dangling Piyush