いくつかのsetter呼び出しに反応できるように、いくつかのクラスMyClassへのすべてのメソッド呼び出しをインターセプトしたいと思います。
動的プロキシを使用しようとしましたが、私が知る限り、これは一部のインターフェイスを実装するクラスでのみ機能します。しかし、MyClassにはそのようなインターフェースはありません。
ラッパークラスを実装する以外に、すべての呼び出しをメンバーに委任する方法はありますか?これは、MyClassのインスタンスであるか、AOPを使用する以外にありますか?
お気づきのとおり、JDK動的プロキシ(インターフェースなし)は使用できませんが、 Spring およびCGLIB(Springに含まれるJAR)を使用すると、次のことができます。
public class Foo
{
public void setBar()
{
throw new UnsupportedOperationException("should not go here");
}
public void redirected()
{
System.out.println("Yiha");
}
}
Foo foo = new Foo();
ProxyFactory pf = new ProxyFactory(foo);
pf.addAdvice(new MethodInterceptor()
{
public Object invoke(MethodInvocation mi) throws Throwable
{
if (mi.getMethod().getName().startsWith("set"))
{
Method redirect = mi.getThis().getClass().getMethod("redirected");
redirect.invoke(mi.getThis());
}
return null;
}
});
Foo proxy = (Foo) pf.getProxy();
proxy.setBar(); // prints "Yiha"
あなたが本当に醜いことをする準備ができているなら、見てください:
http://docs.Oracle.com/javase/7/docs/technotes/guides/jpda/
基本的に、デバッガーインターフェイスでは、デバッガーのようにアタッチできるため、呼び出しをインターセプトできます。これは本当に悪い考えだと思いますが、それが可能かどうか尋ねられたことを覚えておいてください。
この目的のために小さなフレームワークを開発しました。次の場所で確認できます: http://code.google.com/p/Java-interceptor/ (svnを使用して確認してください)。
Javaには、メソッドインターセプト用の実際の言語機能はありません(静的言語にはありません)。
デバッガーインターフェイスを使用するというニックのアイデアが好きです。それはただの意味です。
必要な簡単な答えは次のとおりです。プロキシまたはラッパーを使用してクラスを実際に置き換えることなく、Javaでメソッド呼び出しをインターセプトする方法はありません。
注:AOPライブラリは、これを自動的に実行します。
Javaの達人の一部はこれに眉をひそめるかもしれませんが、プリミティブ型とセッターを完全に回避することである程度の成功を収めました。私のクラスは次のようになります。
class Employee extends SmartPojo {
public SmartString name;
public SmartInt age;
}
2つのことに気付くでしょう:1。すべてが公開されています。 2.コンストラクターはありません。
魔法は、「スマート」インターフェースを実装するフィールドを検索して初期化するSmartPojoで発生します。これはプリミティブではない(そして最終クラスではない)ので、set()メソッドとget()メソッドを追加できますモデル内のすべてのフィールドに対して1か所で。そのため、セッター/ゲッターが無駄になることはもうありません。通知を(1か所に)追加するのは驚くほど簡単です。
確かに、これはもはやPOJOではなく、ほとんどの点でBeanではありませんが、これらの古いアイデアは、役立つ以上に私を制限していることがわかりました。 YMMV。
AspectJには多くの魔法はありません。あなたはあなた自身のエージェントを書くことができます。 http://Java.Sun.com/javase/6/docs/api/Java/lang/instrument/package-summary.html は良い出発点のようです。
クラスがインターフェースを実装できないのはなぜですか?インターセプトするすべてのメソッドを含むインターフェイスをそこから抽出して、動的プロキシメカニズムを簡単に使用できます。クラスではなくインターフェイスを使用してコーディングすることも、優れたプログラミング手法です。
Spring AOP機能(内部で動的プロキシを使用している)を備えたSpringフレームワークを使用してそれを行うことができます。クラスを構成ファイルでSpringBeanとして定義する必要があり、クラスのクライアントは、Springアプリケーションコンテキストからインスタンスを取得するか、依存関係として自動的に取得する必要があります(たとえば、setMyClass(MyClass mc)メソッドを定義することにより) )。そこから、このクラスへのすべてのメソッド呼び出しをインターセプトするアスペクトの定義に簡単に進むことができます。