當前位置:
首頁 > 最新 > Spring Framework 5 權威指南

Spring Framework 5 權威指南

這是一個Spring 5專題系列,其誕生的動機是:

1.介紹最新版本的Spring Framework;

2.介紹最系統化的Spring Framework;

3.介紹最佳實踐的Spring Framework;

3.7代理機制

Spring AOP是基於代理的AOP框架(不同於AspectJ),使用標準的JDK動態代理或CGLIB代理來實現AOP代理(默認取決於目標對象是否實現某個介面)。

要強制使用CGLIB代理,配置如下:

等價的基於schema風格的配置如下:

事務是典型的AOP實現,支持同樣的屬性:

注意:

1.final方法不能被覆蓋,因此也不能被通知;

2.從Spring 3.2開始,CGLIB已經打包到spring-core.jar中;

3.從Spring 4.0開始,CGLIB的代理實例通過Objenesis創建,因此不再調用兩次代理類的構造函數;

在下面的代碼片段中:

publicclassSimplePojoimplementsPojo {

publicvoidfoo() {

//this next method invocation is a direct call on the this reference

this.bar();

}

publicvoidbar() {

//some logic...

}

}

如果你在一個對象引用上調用一個方法,方法將直接在該對象引用上被調用。如下:

publicclassMain{

publicstaticvoidmain(String[]args) {

Pojo pojo =newSimplePojo();

//this is a direct method call on the pojo reference

pojo.foo();

}

}

如果客戶端代碼引用的是代理,如圖:

publicclassMain{

publicstaticvoidmain(String[]args) {

ProxyFactory factory =newProxyFactory(newSimplePojo());

factory.addInterface(Pojo.class);

factory.addAdvice(newRetryAdvice());

Pojo pojo = (Pojo)factory.getProxy();

//this is a method call on the proxy!

pojo.foo();

}

}

由於代理的存在,才使得攔截方法的調用成為可能。但是,目標對象中的自調用方法針對的是this而不是代理引用,因此無法進行攔截。兩種解決辦法,一種是重構代碼以消除自調用,另一種方法則比較變態(與Spring AOP耦合),如下:

publicclassSimplePojoimplementsPojo {

publicvoidfoo() {

//this works, but... gah!

((Pojo)AopContext.currentProxy()).bar();

}

publicvoidbar() {

//some logic...

}

}

客戶端代碼如下:

publicclassMain{

publicstaticvoidmain(String[]args) {

ProxyFactory factory =newProxyFactory(newSimplePojo());

factory.adddInterface(Pojo.class);

factory.addAdvice(newRetryAdvice());

factory.setExposeProxy(true);

Pojo pojo = (Pojo)factory.getProxy();

//this is a method call on the proxy!

pojo.foo();

}

}

注意:如果使用AspectJ則不存在自調用這個問題,因為其不是基於代理的AOP框架。

除了聲明方面以外,還可以通過編程的方式來創建@AspectJ代理以通知目標對象:

// create a factory that cangenerate a proxy for the given target object

AspectJProxyFactory factory =newAspectJProxyFactory(targetObject);

// add an aspect, the classmust be an @AspectJ aspect

// you can call this as many timesas you need with different aspects

factory.addAspect(SecurityManager.class);

// you can also add existingaspect instances, the type of the object supplied must be an @AspectJ aspect

factory.addAspect(usageTracker);

// now get the proxyobject...

MyInterfaceType proxy = factory.getProxy();

TODO:暫時放在這裡

Spring團隊推薦使用基於@AspectJ風格的方面聲明勝過基於schema風格的方面聲明。後者使得代碼和配置分離使得關聯關係不夠直接,並且功能也不夠完善:例如只支持方面的單實例化模型、不能引用已定義的切入點。而前者能同時被Spring AOP框架和AspectJ框架理解。但是,兩種方式也可以並存,其底層是一樣的。多個和片段會被合併為一個AutoProxyCreator。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 全球大搜羅 的精彩文章:

防彈少年團回歸創紀錄 人氣火爆靠數據說話
《果園文學》微刊2017年第016期
世界上最要命的是成為你自己,因為你父母不願意
孩子不懂寬容?不妨這樣做
想看「2 One Another」值回票價?這些「秘密」你不可不知……

TAG:全球大搜羅 |