首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 2.x 中 AOP 的使用淺析

     編輯:Java 相關知識

與 Spring 1.x 相比,Spring 2.x 採用 AspectJ 的語法來宣告 AOP,使其更加標準化且靈活。若您不熟悉 AspectJ 卻打算使用 Spring 2.x 的 AspectJ 風格 AOP,建議先學習 AspectJ 相關知識,市面上有許多相關書籍可供參考。

Spring 2.x 下的切面有兩種實現方式:一種是以 Java 類定義切面(普通 Java 類),再在配置檔中宣告;另一種是在 Java 類中引入 AOP 相關的元資料(註解)。

第一種:XML 配置方式

需注意的是,Spring 2.x 的 beans 名稱空間與 1.x 不同,它採用 Schema 而非 DTD(仍可使用 DTD,詳見文件)。以無意義的日誌切面為例,定義切面類 LoggingAspect 如下:

public class LoggingAspect {
    public void logMethod(JoinPoint jp) {
        System.err.println(jp.getTarget().getClass());
        System.err.println(jp.getSignature().getName());
    }
}

在配置檔中進行如下配置:

<bean id="logAspectTarget" class="hibernatesample.service.util.LoggingAspect" />
<aop:config>
    <aop:aspect id="logAspect" ref="logAspectTarget">
        <aop:pointcut id="businessService" expression="execution(* hibernatesample.service.*.*(..))" />
        <aop:after pointcut-ref="businessService" method="logMethod" />
    </aop:aspect>
</aop:config>

上述切面中,切入點 businessService 在配置檔中宣告,其運算式採用 AspectJ 語法。LoggingAspect 類的 logMethod(JoinPoint jp) 方法根據配置可知為 after 通知,JoinPoint 參數非必須,它來自 AspectJ 的工具類,此處用於輸出連接點相關資訊。Spring 2.x 中,切入點與通知的使用更靈活,可像 AspectJ 一樣傳遞參數給通知。

若需在 Service 中引入事務功能,需配置事務通知:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="get*" read-only="true" />
        <tx:method name="find*" read-only="true" />
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="demoServiceMethods" expression="execution(* hibernatesample.service.*.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="demoServiceMethods" />
    <aop:aspect id="logAspect" ref="logAspectTarget">
        <aop:pointcut id="businessService" expression="execution(* hibernatesample.service.*.*(..))" />
        <aop:after pointcut-ref="businessService" method="logMethod" />
    </aop:aspect>
</aop:config>

完成上述工作相當於完成了 Spring 1.x 的自動代理。之後定義的任何 Service Bean 都能保持純粹:

<bean id="accountService" class="hibernatesample.service.impl.AccountServiceImpl">
    <property name="accountDAO" ref="accountDAO" />
</bean>

第二種:註解方式

與第一種相比,僅在 LoggingAspect 中加入註解,並省去配置檔中關於 logAspect 的配置。重寫後的 LoggingAspect 如下:

@Aspect
public class LoggingAspect {
    @Pointcut("execution(* hibernatesample.service.*.*(..))")
    public void businessService() {}
    @After("businessService()")
    public void logMethod(JoinPoint jp) {
        System.err.println(jp.getTarget().getClass());
        System.err.println(jp.getSignature().getName());
    }
}

簡化後的配置檔可移除與 logAspect 相關的配置:

<aop:aspect id="logAspect" ref="logAspectTarget">
    <aop:pointcut id="businessService" expression="execution(* hibernatesample.service.*.*(..))" />
    <aop:after pointcut-ref="businessService" method="logMethod" />
</aop:aspect>
<bean id="logAspectTarget" class="hibernatesample.service.util.LoggingAspect" />

為使 Spring 應用 LoggingAspect 的註解,需在配置檔中添加:

<aop:aspectj-autoproxy/>

若覺得事務配置未使用註解更簡潔(筆者不這麼認為,畢竟配置檔中的事務宣告相對固定,除非作用於類上的事務邏輯極其複雜),也可使用 Spring 提供的事務註解作用於類上,實現更細粒度的事務宣告。

坦白說,因時間有限,本文略顯粗糙。對 Spring AOP 有興趣且有疑問的讀者,建議參考 Spring 官方文件,其文件質量尚可。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved