:: 首頁 ::  :: 聯系 :: 聚合  :: 管理

          Spring技術手冊筆記(二):Spring AOP

          Posted on 2009-11-08 20:12 codingliyi 閱讀(601) 評論(0)  編輯  收藏 所屬分類: Java EE

          四、SpringAOP

          學習AOP必須首先要學習代理模式。詳見我的上一篇筆記:AOP基礎:動態代理

          AOP觀念與術語

          1.橫切關注點(Cross-cutting concern

          類似于日志記錄、安全檢查、事務等系統層面的服務,在一些應用程序中常被尖刀安插至各個對象的處理流程中,這些動作在AOP術語中被稱為橫切關注點。

          2.切面(Aspect

          將散落于各個業務對象中的橫切關注點(如日志記錄)收集起來,設計各個獨立可重用的對象,這些對象被稱為切面。如上篇筆記中的Handler類。在需要該服務時,織入(Weave)應用程序之上。

          3.Advice

          Aspect的具體實現被稱之為Advice。例如,Advice中會包括日志記錄程序代碼是如何實現的。Advice中包含了橫切關注點的行為或提供的服務。

          4.Joinpoint

          Aspect在應用程序執行時加入業務流程的點或時機。這個時機可能是某個方法執行之前或之后或兩者都有,或是某個異常發生的時候。

          5.Pointcut

          Pointcut是一個定義,可在某個定義文件中編寫Pointcut,指定某個Aspect在哪些Joinpoint時被織入。

          Spring AOP

          SpringAdvice是在執行時期導入至Targets的,可以讓Target實現預先定義的接口,則Spring在執行時會使用動態代理;如不實現接口,則會使用CGLIBTarget產生一個子類作為代理類。

          Spring只支持方法的Joinpoints,即Advices將在方法執行的前后調用。

          Advices

          Advices包括Aspect的真正邏輯,具體說來就是一個類,由于織入至Targets的時機不同,Spring提供了幾種不同的Advices,如BeforeAdviceAfterAdviceArountAdviceThrowAdvice

          BeforeAdvice

          通過實現org.springframework.aop.MethodBeforeAdvice接口來實現邏輯。

          該接口定義如下方法:

          public void before(Method method, Object[] args, Object target)

          throws Throwable;

          Before()方法聲明為void,所以不用回傳任何結果,在before()執行完畢之后,除非拋出異常,否則目標對象上的方法就會被執行。

          示例代碼如下:

          1public class LogBeforeAdvice implements MethodBeforeAdvice {
          2    Logger logger = Logger.getLogger(this.getClass().getName());
          3    public void before(Method method, Object[] args, Object target)
          4            throws Throwable {
          5        logger.log(Level.INFO,"Method starts");
          6    }

          7}
          在配置文件中寫入以下內容:
           1<bean id="logBeforeAdvice" class="SpringAOP.LogBeforeAdvice"></bean>
           2
           3<bean id="helloSpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
           4    <!-- 如果下一行代碼去掉,Spring將會使用CGLIB創建一個代理類 -->
           5    <property name="proxyInterfaces" value="SpringAOP.IHello"></property>
           6    <property name="target" ref="helloSpeaker"></property>
           7    <property name="interceptorNames">
           8        <list>
           9            <value>logBeforeAdvice</value>
          10        </list>
          11    </property>
          12</bean>

          AfterAdvice

          通過實現org.springframework.aop.AfterReturningAdvice接口來實現。

          該接口定義如下方法:

          public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;

          示例代碼類似于BeforeAdvice

          AroundAdvice

          通過實現org.aopalliance.intercept.MethodIntercept接口來實現。

          該接口定義如下方法:

          public Object invoke(MethodInvocation methodInvocation) throws Throwable;

          示例代碼如下:

           1import org.aopalliance.intercept.MethodInterceptor;
           2import org.aopalliance.intercept.MethodInvocation;
           3
           4public class LogAroundAdvice implements MethodInterceptor {
           5    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
           6        System.out.println("AroundAdvice Begin");
           7        Object result = methodInvocation.proceed();
           8        System.out.println("AroundAdvice Finish");
           9        return result;
          10    }

          11}
          配置文件類似于BeforeAdvice。

          ThrowAdvice

          通過實現org.springframework.aop.ThrowAdvice接口來實現。

          該接口只是個標簽接口,沒有任何方法。可以定義任意方法名稱,只要是如下形式:

          methodName([Method], [args], [target], subclassOfThrowable);

          其中[]表示可選。subclassOfThrowable必須是Throwable的子類。當異常發生時,會檢驗所設定的Throw Advice中是否有符合異常類型的方法,如有則執行。

          注意:當異常發生時,ThrowAdvice的任務只是執行對應的方法,并不能處理異常。當其執行完畢后,原來的異常仍被傳播至應用程序之中。

          PointcutAdvisor

          Spring中,可以指定更精細的織入時機,Pointcut定義了Advice的應用時機,在Spring中,使用PointcutAdvisorPointcutAdvice結合成一個對象。Spring內建的Pointcut都有對應的PointcutAdvisor

          1Public interface Advisor{
          2boolean isPerInstance();
          3Advice getAdvice();
          4}

          5Public interface PointcutAdvisor extends Advisor{
          6Pointcut getPointcut()
          7}

          NameMatchMethodPointcutAdvisor

          這是最基本的PointcutAdvisor。可以指定所要應用的目標上的方法名稱。

          示例代碼:

           1<bean id="helloPointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
           2    <property name="mappedName">
           3        <value>say*</value>
           4    </property>
           5    <property name="advice">
           6        <ref bean="logAroundAdvice"/>
           7    </property>
           8</bean>
           9
          10<bean id="helloSpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
          11    <!-- 如果下一行代碼去掉,Spring將會使用CGLIB創建一個代理類 -->
          12    <property name="proxyInterfaces" value="SpringAOP.IHello"></property>
          13    <property name="target" ref="helloSpeaker"></property>
          14    <property name="interceptorNames">
          15        <list>
          16            <!-- 
          17            <value>logBeforeAdvice</value>
          18            <value>logAfterAdvice</value>
          19            <value>logAroundAdvice</value>
          20             -->
          21            <value>helloPointcutAdvisor</value>
          22        </list>
          23    </property>
          24</bean>

          Autoproxy

          自動代理可以不用為每一個目標對象手動定義代理對象,使用自動代理,可以透過Bean名稱或是Pointcut的比對,自動為符合比對條件的目標對象建立代理對象。

          BeanNameAutoProxyCreator

          當應用程序很大時,可以為目標對象取好適當的Bean名稱,例如xxxService。此時可修改Bean定義文件如下:

           1<bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
           2    <property name="beanNames">
           3        <list>
           4            <value>*Speaker</value>
           5        </list>
           6    </property>
           7    <property name="interceptorNames">
           8        <list>
           9            <value>logAroundAdvice</value>
          10        </list>
          11    </property>
          12</bean>
          主站蜘蛛池模板: 高雄市| 阿克| 普格县| 梧州市| 舟曲县| 尉犁县| 类乌齐县| 呼玛县| 克东县| 城市| 治多县| 邵阳县| 辰溪县| 和平区| 四川省| 大埔区| 衡山县| 东城区| 孝感市| 同仁县| 济阳县| 聂荣县| 黑山县| 固镇县| 山丹县| 黔西| 阜新市| 鹰潭市| 西充县| 革吉县| 敦煌市| 阿图什市| 新乐市| 五常市| 鄂托克前旗| 凤庆县| 泸溪县| 柘荣县| 抚顺县| 吴堡县| 莱州市|