7.6 Proxying mechanisms

7.6 Proxying mechanisms

SpringAOPでは、JDK DynamicProyとCGLIBのどちらかを選択できる。(JDK DynamicProxyが優先される。)
もしJDK DynamicProxyを使う場合は、アスペクトの対象となるオブジェクトは最低でもひとつのインタフェースを実装する必要がある。対象のクラスが実装したインタフェースがProxy化の対象となる。もし対象のオブジェクトがインタフェースを実装していない場合は、CGLIBによりProxy化される。

もしCGLIBによるProxy化を強制したい(インタフェースを実装していないクラスにだけ適用するのではなく常に適用する)場合はそうすることもできるが、この場合いくつかの考慮点がる。

  1. finalメソッドに対してはアドバイスできない。なぜならこれらはオーバライドできないからである。
  2. CGLIBのjarをクラスパスに通す必要がある(あたりまえ)
  3. Proxy化されるオブジェクトのコンストラクタは2回呼び出される。これはCGLIBのプロキシモデル(プロキシクラスは、プロキシ化対象クラスのサブクラスとなる)を考えると自然の成り行きである。プロキシ化対象毎に、プロキシ化される実際にオブジェクトと、アドバイスを実装するプロキシ化対象のサブクラスの二つのインスタンスが生成される。JDK DynamicProxyではこのようなことはない。普通はこのことは問題にならない。ただ、コンストラクタに実際のビジネスロジックを書き始めると問題になるので、そういう事はやめてください。

CGLIBによるProxy生成を強制するにはこうすれば良いです。


<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>

またアノテーションベース(@AspectJ autoproxy)を採用する場合はこうすれば良いです。


<aop:aspectj-autoproxy proxy-target-class="true"/>


7.6.1 Understanding AOP proxies

AOP proxiesのモデルは、サーブレットで言うところのフィルタみたいなモデルです(詳細割愛)。よって、プロキシ対象のインスタンスが自分のインスタンスメソッドを再帰的に呼び出す場合はアスペクトが適用されないことに注意してください。もしプロキシ対象のインスタンスが、自分のインスタンスを呼び出す場合はこうする必要がある。こうするとSpringに依存しちゃうしカッコ悪いのでやめたほうが良いです(別クラスの別メソッドにリファクタリングすべき)

・設定ファイル


<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>

ソースコード


@Component
public class Bean{
public String hello(String s){
System.out.println("-----");
Bean bean = (Bean)AopContext.currentProxy();
bean.fuga();
return "bye";
}

public void fuga(){
System.out.println("*****");
}
}