java代理與Spring AOP


代理模式是經常使用的Java 設計模式,它的特徵是代理類與委託類有一樣的接口,代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及過後處理消息等。代理類與委託類之間一般會存在關聯關係,一個代理類的對象與一個委託類的對象關聯,代理類的對象自己並不真正實現服務,而是經過調用委託類的對象的相關方法,來提供特定的服務。按照代理類的建立時期,代理類可分爲兩種。

靜態代理類:
由程序員建立或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。動態代理類:在程序運行時,運用反射機制動態建立而成。

因而可知,靜態代理類能夠爲委託類預處理消息、把消息轉發給委託類和過後處理消息等。  也就是委託模式。

動態代理類
與靜態代理類對照的是動態代理類,動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不只簡化了編程工做,並且提升了軟件系統的可擴展性,由於Java 反射機制能夠生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力。  

Spring中的AOP便是代理模式的一種框架級使用

Spring中有使用三種技術實現功能代理;
1.Java動態代理
2.CGlib
3.Aspectj

Spring AOP模式
默認模式
默認Spring使用java動態代理與CGlib混合的代理方式提供服務,即若對象類實現了接口則Spring自動採用java動態代理進行支持,不然採用CGlib進行支持;這中間隱含的是對效率的選擇,cglib的效率要略低於java自帶動態代理;

固然也能夠強制指定使用cglib來進行代理,方法是在xml中配置<aop:aspectj-autoproxy 
proxy-target-class=」true」 />進行開啓;

使用Spring AOP默認模式的優勢是使用簡單,不須要LTW(load-time weave)支持,但其缺點是存在自調用方法沒法織入的問題(self-invocation issue);

如:類C有方法A,B,
      class C{
        publich void A(){
            System.out.println("A");
            B();
        }

        publich void B(){
            System.out.println("B");
        }
      }
    
若對C類全部方法代理在進入時均輸出X
    public X{
        
@Around("execution(* *(..))") java

public void logBefore(ProceedingJoinPoint joinPoint) {
            System.out.println("X");
            try {
joinPoint.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
        }
    }
指望其輸出結果爲
X
A
X
B//即A,B方法均被代理

但結果爲
X
A
B//可見A調用同對象方法B時未被代理

該問題產生的根本緣由是因爲java動態代理與cglib均是採用運行時織入代理方法新生成代理類來,目標類委託給代理類進行處理;
簡稱代理類爲P
調用A方法時調用的實際上是P的A方法;
A調用B時,調用的是其目標對象的B方法,即C.B(),而非P.B()
這個問題對於Aspectj模式是不存在的

Aspectj模式

Spring中使用Aspectj是經過LTW修改原類字節碼的法來生成代理;

不會生成新的代理類,也就不存在自調用方法沒法織入的問題

但其缺點是,程序啓動時必須指定javaagent爲spring-agent.jar,即-javaagent:D:/spring-agent.jar

另外與默認AOP模式不同的點在於aop.xml配置文件,默認AOP模式中不須要單獨設定AOP文件,其經過<aop:aspectj-autoproxy/> 可自動掃描進行織入;

Aspectj模式中aop.xml默認須要放在META-INF中,Aspectj會掃描全部classpath中的META-INF/aop.xml文件;
某些狀況下(好比測試時),咱們但願能夠指定aop.xml文件的位置,這時能夠經過指定java運行參數
-Dorg.aspectj.weaver.loadtime.configuration=test/myaop.xml
但須要注意的是文件位置必須是類路徑,不能使用文件系統路徑

整合起來啓動參數爲 -javaagent:D:/spring-agent.jar  -Dorg.aspectj.weaver.loadtime.configuration=test/aop.xml

說的比較苦澀,附件有更詳細的代碼能夠試運行下就明白了  程序員

代碼下載:http://vdisk.weibo.com/s/mYJmX
spring

相關文章
相關標籤/搜索