日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringAop与AspectJ的联系与区别____比较分析 Spring AOP 和 AspectJ 之间的差别

發布時間:2025/3/12 javascript 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringAop与AspectJ的联系与区别____比较分析 Spring AOP 和 AspectJ 之间的差别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SpringAop與AspectJ的聯系與區別

區別

AspectJ

AspectJ是一個面向切面的框架,它擴展了Java語言。AspectJ定義了AOP語法,所以它有一個專門的編譯器用來生成遵守Java字節編碼規范的Class文件。

spring aop

Spring提供了四種類型的Aop支持
* 基于經典的SpringAOP
* 純POJO切面
* @ASpectJ注解驅動的切面
* 注入式AspectJ切面(其實與Spring并無多大的關系,這個就是使用AspectJ這個框架實現Aop編程)

基于經典的SpringAop

其使用ProxyFactoryBean創建:
增強(通知)的類型有:
前置通知:org.springframework.aop.MethodBeforeAdvice
后置通知:org.springframework.aop.AfterReturningAdvice
環繞通知:org.aopalliance.intercept.MethodInterceptor
異常通知:org.springframework.aop.ThrowsAdvice

public interface IBookDao {public int add()public int delete(); }public class BookDaoImpl implements IBookDao{public int add() {System.out.println("正在添加圖書...");return 0;}public int delete() {System.out.println("正在刪除圖書...");return 0;} }//實現了MethodInterceptor的環繞增強類 public class MyAdvice implements MethodInterceptor{public Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("Around Advice before method invocation");Object o = invocation.proceed();System.out.println("Around Advice after method invocation");return o;} } //將每一個連接點都當做切點(攔截每一個方法) <bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean><bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean><bean id="bookDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="bookDao"/><property name="proxyInterfaces" value="com.njust.learning.spring.service.IBookDao"/><property name="interceptorNames" value="myadvice"/></bean>12345678910 使用RegexMethodPointcutAdvisor針對某些特定的方法進行攔截增強 <bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean><bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean><bean id="rmpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><!--patterns,如果有多個指定的值的話,可以使用,隔開,例如value=".*add,.*delete"--><property name="patterns" value=".*add"/><property name="advice" ref="myadvice"/></bean> <!--使用的時候使用這個id,而不是原始的那個id--><bean id="bookDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="bookDao"/><property name="proxyInterfaces" value="com.njust.learning.spring.service.IBookDao"/><property name="interceptorNames" value="rmpAdvisor"/></bean>
注意

像上面這樣,每定義一個dao都需要定義一個ProxyFactoryBean,顯得很麻煩,所以我們引入自動代理,也就是自動創建代理對象

BeanNameAutoProxyCreator

<bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean><bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean><bean id="rmpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><!--patterns,如果有多個指定的值的話,可以使用,隔開,例如value=".*add,.*delete"--><property name="patterns" value=".*add"/><property name="advice" ref="myadvice"/></bean><bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><property name="beanNames" value="*Dao"></property><property name="interceptorNames" value="rmpAdvisor"></property></bean>

DefaultAdvisorAutoProxyCreator

<bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean><bean id="myadvice" class="com.njust.learning.spring.aop.MyAdvice"></bean><bean id="rmpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><!--patterns,如果有多個指定的值的話,可以使用,隔開,例如value=".*add,.*delete"--><property name="patterns" value=".*add"/><property name="advice" ref="myadvice"/></bean><!--根據切面中生成信息生成代理--><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>1234567891011

純POJO切面,需要使用XML進行配置

public interface IBookDao {public int add();public int delete(); }public class BookDaoImpl implements IBookDao{public int add() {int a = 1/0;System.out.println("正在添加圖書...");return 0;}public int delete() {System.out.println("正在刪除圖書...");return 0;} } public class PojoAdvice {public void before(){System.out.println("前置通知");}public void after(Object returnval){System.out.println("后置通知"+",處理后的結果為:"+returnval);}public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("環繞前置增強...");Object o = proceedingJoinPoint.proceed();System.out.println("環繞后置增強...");return o;}public void afterThrowing(Throwable e){System.out.println("異常通知:"+e.getMessage());} } <bean id="bookDao" class="com.njust.learning.spring.service.BookDaoImpl"></bean><bean id="pojoAdvice" class="com.njust.learning.spring.pojoaop.PojoAdvice"></bean><aop:config><aop:pointcut id="p" expression="execution (* *.add(..))"/><aop:aspect ref="pojoAdvice"><aop:before method="before" pointcut-ref="p"></aop:before><!--通過設置returning來將返回值傳遞給通知--><aop:after-returning method="after" pointcut-ref="p" returning="returnval"/><aop:around method="around" pointcut-ref="p"/><!--通過設置returning來將異常對象傳遞給通知--><aop:after-throwing method="afterThrowing" pointcut-ref="p" throwing="e"/></aop:aspect></aop:config>

聯系

我們借助于Spring Aop的命名空間可以將純POJO轉換為切面,實際上這些POJO只是提供了滿足切點的條件時所需要調用的方法,但是,這種技術需要XML進行配置,不能支持注解
所以spring借鑒了AspectJ的切面,以提供注解驅動的AOP,本質上它依然是Spring基于代理的AOP,只是編程模型與AspectJ完全一致,這種風格的好處就是不需要使用XML進行配置




比較分析 Spring AOP 和 AspectJ 之間的差別

AOP(Aspect OrientedProgramming, 面向切面/方面編程) 旨在從業務邏輯中分離出來橫切邏輯【eg:性能監控、日志記錄、權限控制等】,提高模塊化,即通過AOP解決代碼耦合問題,讓職責更加單一。

運用技術:

? SpringAOP使用了兩種代理機制,一種是基于JDK的動態代理,另一種是基于CGLib的動態代理,之所以需要兩種代理機制,很大程度上是因為JDK本身只提供基于接口的代理,不支持類的代理。

切面植入的方法:

  • 編譯期織入

  • 類裝載期織入

  • 動態代理織入---->在運行期為目標類添加增強生成子類的方式,Spring AOP采用動態代理織入切面

  • 流行的框架:

    AOP現有兩個主要的流行框架,即Spring AOP和Spring+AspectJ

    二者的區別:

    1、 織入的時期不同

    Spring Aop采用的動態織入,而Aspectj是靜態織入。靜態織入:指在編譯時期就織入,即:編譯出來的class文件,字節碼就已經被織入了。動態織入又分靜動兩種,靜則指織入過程只在第一次調用時執行;動則指根據代碼動態運行的中間狀態來決定如何操作,每次調用Target的時候都執行。有不清楚的同學,可以自己補下基礎的代理知識

    2、從使用對象不同

    Spring AOP的通知是基于該對象是SpringBean對象才可以,而AspectJ可以在任何Java對象上應用通知。

    Spring AOP:如果你想要在通過this對象調用的方法上應用通知,那么你必須使用currentProxy對象,并調用其上的相應方法;于此相似,如果你想要在某對象的方法上應用通知,那么你必須使用與該對象相應的Spring bean

    AspectJ:使用AspectJ的一個間接局限是,因為AspectJ通知可以應用于POJO之上,它有可能將通知應用于一個已配置的通知之上。對于一個你沒有注意到這方面問題的大范圍應用的通知,這有可能導致一個無限循環。

    Spring AOP不同于大多數其他AOP框架。Spring AOP的目的并不是為了提供最完整的AOP實現(雖然Spring AOP具有相當的能力);而是為了要幫助解決企業應用中的常見問題,提供一個AOP實現與Spring IOC之間的緊密集成。由于Spring AOP是容易實現的,如果你計劃在Spring Beans之上將橫切關注點模塊化,Spring的這一目標將是要點之一。但同樣的目標也可能成為一個限制,如果你用的是普通的Java對象而不是Spring beans,并基于此將橫切關注點模塊化的話。另一方面,AspectJ可用于基于普通Java對象的模塊化,但在實施之前需要良好的關于這個主題的知識。

    在決定使用哪種框架實現你的項目之前,有幾個要點可以幫助你做出合適的選擇(同樣適用于其他框架)。

    明確你在應用橫切關注點(cross-cutting concern)時(例如事物管理、日志或性能評估),需要處理的是Spring beans還是POJO。如果正在開發新的應用,則選擇Spring AOP就沒有什么阻力。但是如果你正在維護一個現有的應用(該應用并沒有使用Spring框架),AspectJ就將是一個自然的選擇了。為了詳細說明這一點,假如你正在使用Spring AOP,當你想將日志功能作為一個通知(advice)加入到你的應用中,用于追蹤程序流程,那么該通知(Advice)就只能應用在Spring beans的連接點(Joinpoint)之上

    例子:在appbeans.xml中配置如下的切入點(pointcut),那么當調用myServices bean的service方法時就將應用日志通知(advice)。

    <!Configuration snippet in appbeans.xml --><bean id="myServices" class="com.ashutosh.MyServicesImpl " /><aop:config><aop:aspect id="loggingAspect" ref="logging"><aop:around method="log" pointcut="execution(public * *(..))"/></aop:aspect></aop:config --> // Java file calling service methodApplicationContext beans =newClassPathXmlApplicationContext("appbeans.xml");MyServices myServices = (MyServices) beans.getBean("myServices");myServices.service(); // Logging advice applied here

    看一下日志通知將要被應用處的注釋,在這里應用程序將記錄被調用方法的詳細信息。但是,當你在service()方法中調用同一個類中的其他方法時,如果你沒有使用代理對象,那么日志通知就不會被應用到這個方法調用上。

    例如:

    // MyServices service methodpublic void service() {performOperation();// Logging advice not going to apply here}

    如果你想要在通過this對象調用的方法上應用通知,那么你必須使用currentProxy對象,并調用其上的相應方法。

    // MyServices service methodpublic void service() {// Logging advice going to apply here((MyServices) AopContext.currentProxy()).performOperation();}

    于此相似,如果你想要在某對象的方法上應用通知,那么你必須使用與該對象相應的Spring bean。

    public void service() {MyObject obj = new MyObject();Obj.performOperation();// Logging advice not going to apply here}

    如果你想要應用該通知,那么上述代碼必須修改為如下形式。

    public void service() {MyObject obj = new MyObject();Obj.performOperation();// Logging advice not going to apply hereApplicationContext beans =newClassPathXmlApplicationContext("appbeans.xml");MyObject obj =(MyObject) beans.getBean("myObject");obj.performOperation()// Logging advice applied here}

    于此不同,使用“AspectJ”你可以在任何Java對象上應用通知,而不需要在任何文件中創建或配置任何bean。

    另一個需要考慮的因素是,你是希望在編譯期間進行織入(weaving),還是編譯后(post-compile)或是運行時(run-time)。Spring只支持運行時織入。如果你有多個團隊分別開發多個使用Spring編寫的模塊(導致生成多個jar文件,例如每個模塊一個jar文件),并且其中一個團隊想要在整個項目中的所有Spring bean(例如,包括已經被其他團隊打包了的jar文件)上應用日志通知(在這里日志只是用于加入橫切關注點的舉例),那么通過配置該團隊自己的Spring配置文件就可以輕松做到這一點。之所以可以這樣做,就是因為Spring使用的是運行時織入。

    <!Configuration --><bean id="myServices" class="com.ashutosh.MyServicesImpl " /><aop:config><aop:aspect id="loggingAspect" ref="logging"><aop:around method="log" pointcut="execution(public * *(..))"/></aop:aspect></aop:config -->

    如果你使用AspectJ想要做到同樣的事情,你也許就需要使用acj(AspectJ編譯器)重新編譯所有的代碼并且進行重新打包。否則,你也可以選擇使用AspectJ編譯后(post-compile)或載入時(load-time)織入。

    因為Spring基于代理模式(使用CGLIB),它有一個使用限制,即無法在使用final修飾的bean上應用橫切關注點。因為代理需要對Java類進行繼承,一旦使用了關鍵字final,這將是無法做到的。

    例如,在Spring bean MyServicesImpl上使用關鍵字final,并配置一個“execution(public * *(…))”這樣的切入點,將導致運行時異常(exception),因為Spring不能為MyServicesImpl生成代理。

    // Configuration file<bean id="myServices" class="com.ashutosh.MyServicesImpl" />//Java filepublic final classMyServicesImpl {---}

    在這種情況下,你也許會考慮使用AspectJ,其支持編譯期織入且不需要生成代理。

    于此相似,在static和final方法上應用橫切關注點也是無法做到的。因為Spring基于代理模式。如果你在這些方法上配置通知,將導致運行時異常,因為static和final方法是不能被覆蓋的。在這種情況下,你也會考慮使用AspectJ,因為其支持編譯期織入且不需要生成代理。

    你一定希望使用一種易于實現的方式。因為Spring AOP支持注解,在使用@Aspect注解創建和配置方面時將更加方便。而使用AspectJ,你就需要通過.aj文件來創建方面,并且需要使用ajc(Aspect編譯器)來編譯代碼。所以如果你確定之前提到的限制不會成為你的項目的障礙時,使用Spring AOP。

    使用AspectJ的一個間接局限是,因為AspectJ通知可以應用于POJO之上,它有可能將通知應用于一個已配置的通知之上。對于一個你沒有注意到這方面問題的大范圍應用的通知,這有可能導致一個無限循環。

    例如,創建一個包含如下切入點的方面。

    public aspectLogging {Object around() : execution(public * * (..))Sysytem.out.println(thisJoinPoint.getSignature());return proceed();}

    在這種情況下,當proceed即將被調用時,日志通知會被再次應用,這樣就導致了嵌套循環。

    所以,如果你希望在Spring bean上采取比較簡單的方式應用橫切關注點時,并且這些bean沒有被標以final修飾符,同時相似的方法也沒有標以static或final修飾符時,就使用Spring AOP吧。相比之下,如果你需要在所提到的限制之上應用橫切關注點,或者要在POJO上應用關注點,那么就使用AspectJ。你也可能選擇同時使用兩種方法,因為Spring支持這樣。

    參考鏈接:http://docs.spring.io/spring/docs/3.0.x/reference/aop.html

    http://www.oschina.net/translate/comparative_analysis_between_spring_aop_and_aspectj?cmp

    總結

    以上是生活随笔為你收集整理的SpringAop与AspectJ的联系与区别____比较分析 Spring AOP 和 AspectJ 之间的差别的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。