:: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理

          Spring技術(shù)手冊(cè)筆記(二):Spring AOP

          Posted on 2009-11-08 20:12 codingliyi 閱讀(605) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Java EE

          四、SpringAOP

          學(xué)習(xí)AOP必須首先要學(xué)習(xí)代理模式。詳見(jiàn)我的上一篇筆記:AOP基礎(chǔ):動(dòng)態(tài)代理

          AOP觀念與術(shù)語(yǔ)

          1.橫切關(guān)注點(diǎn)(Cross-cutting concern

          類(lèi)似于日志記錄、安全檢查、事務(wù)等系統(tǒng)層面的服務(wù),在一些應(yīng)用程序中常被尖刀安插至各個(gè)對(duì)象的處理流程中,這些動(dòng)作在AOP術(shù)語(yǔ)中被稱(chēng)為橫切關(guān)注點(diǎn)。

          2.切面(Aspect

          將散落于各個(gè)業(yè)務(wù)對(duì)象中的橫切關(guān)注點(diǎn)(如日志記錄)收集起來(lái),設(shè)計(jì)各個(gè)獨(dú)立可重用的對(duì)象,這些對(duì)象被稱(chēng)為切面。如上篇筆記中的Handler類(lèi)。在需要該服務(wù)時(shí),織入(Weave)應(yīng)用程序之上。

          3.Advice

          Aspect的具體實(shí)現(xiàn)被稱(chēng)之為Advice。例如,Advice中會(huì)包括日志記錄程序代碼是如何實(shí)現(xiàn)的。Advice中包含了橫切關(guān)注點(diǎn)的行為或提供的服務(wù)。

          4.Joinpoint

          Aspect在應(yīng)用程序執(zhí)行時(shí)加入業(yè)務(wù)流程的點(diǎn)或時(shí)機(jī)。這個(gè)時(shí)機(jī)可能是某個(gè)方法執(zhí)行之前或之后或兩者都有,或是某個(gè)異常發(fā)生的時(shí)候。

          5.Pointcut

          Pointcut是一個(gè)定義,可在某個(gè)定義文件中編寫(xiě)Pointcut,指定某個(gè)Aspect在哪些Joinpoint時(shí)被織入。

          Spring AOP

          SpringAdvice是在執(zhí)行時(shí)期導(dǎo)入至Targets的,可以讓Target實(shí)現(xiàn)預(yù)先定義的接口,則Spring在執(zhí)行時(shí)會(huì)使用動(dòng)態(tài)代理;如不實(shí)現(xiàn)接口,則會(huì)使用CGLIBTarget產(chǎn)生一個(gè)子類(lèi)作為代理類(lèi)。

          Spring只支持方法的Joinpoints,即Advices將在方法執(zhí)行的前后調(diào)用。

          Advices

          Advices包括Aspect的真正邏輯,具體說(shuō)來(lái)就是一個(gè)類(lèi),由于織入至Targets的時(shí)機(jī)不同,Spring提供了幾種不同的Advices,如BeforeAdviceAfterAdviceArountAdviceThrowAdvice

          BeforeAdvice

          通過(guò)實(shí)現(xiàn)org.springframework.aop.MethodBeforeAdvice接口來(lái)實(shí)現(xiàn)邏輯。

          該接口定義如下方法:

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

          throws Throwable;

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

          示例代碼如下:

          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}
          在配置文件中寫(xiě)入以下內(nèi)容:
           1<bean id="logBeforeAdvice" class="SpringAOP.LogBeforeAdvice"></bean>
           2
           3<bean id="helloSpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
           4    <!-- 如果下一行代碼去掉,Spring將會(huì)使用CGLIB創(chuàng)建一個(gè)代理類(lèi) -->
           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

          通過(guò)實(shí)現(xiàn)org.springframework.aop.AfterReturningAdvice接口來(lái)實(shí)現(xiàn)。

          該接口定義如下方法:

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

          示例代碼類(lèi)似于BeforeAdvice

          AroundAdvice

          通過(guò)實(shí)現(xiàn)org.aopalliance.intercept.MethodIntercept接口來(lái)實(shí)現(xiàn)。

          該接口定義如下方法:

          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}
          配置文件類(lèi)似于BeforeAdvice。

          ThrowAdvice

          通過(guò)實(shí)現(xiàn)org.springframework.aop.ThrowAdvice接口來(lái)實(shí)現(xiàn)。

          該接口只是個(gè)標(biāo)簽接口,沒(méi)有任何方法。可以定義任意方法名稱(chēng),只要是如下形式:

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

          其中[]表示可選。subclassOfThrowable必須是Throwable的子類(lèi)。當(dāng)異常發(fā)生時(shí),會(huì)檢驗(yàn)所設(shè)定的Throw Advice中是否有符合異常類(lèi)型的方法,如有則執(zhí)行。

          注意:當(dāng)異常發(fā)生時(shí),ThrowAdvice的任務(wù)只是執(zhí)行對(duì)應(yīng)的方法,并不能處理異常。當(dāng)其執(zhí)行完畢后,原來(lái)的異常仍被傳播至應(yīng)用程序之中。

          PointcutAdvisor

          Spring中,可以指定更精細(xì)的織入時(shí)機(jī),Pointcut定義了Advice的應(yīng)用時(shí)機(jī),在Spring中,使用PointcutAdvisorPointcutAdvice結(jié)合成一個(gè)對(duì)象。Spring內(nèi)建的Pointcut都有對(duì)應(yīng)的PointcutAdvisor

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

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

          NameMatchMethodPointcutAdvisor

          這是最基本的PointcutAdvisor。可以指定所要應(yīng)用的目標(biāo)上的方法名稱(chēng)。

          示例代碼:

           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將會(huì)使用CGLIB創(chuàng)建一個(gè)代理類(lèi) -->
          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

          自動(dòng)代理可以不用為每一個(gè)目標(biāo)對(duì)象手動(dòng)定義代理對(duì)象,使用自動(dòng)代理,可以透過(guò)Bean名稱(chēng)或是Pointcut的比對(duì),自動(dòng)為符合比對(duì)條件的目標(biāo)對(duì)象建立代理對(duì)象。

          BeanNameAutoProxyCreator

          當(dāng)應(yīng)用程序很大時(shí),可以為目標(biāo)對(duì)象取好適當(dāng)?shù)?font face="Courier New">Bean名稱(chēng),例如xxxService。此時(shí)可修改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>
          主站蜘蛛池模板: 十堰市| 连云港市| 嫩江县| 余江县| 博湖县| 申扎县| 濮阳市| 嵊泗县| 调兵山市| 巫山县| 永丰县| 衡山县| 金堂县| 阿合奇县| 铜梁县| 曲阳县| 台前县| 景宁| 长春市| 克什克腾旗| 五台县| 阜阳市| 岳阳市| 开远市| 德化县| 江油市| 永嘉县| 金平| 江安县| 钦州市| 肃北| 宜良县| 临泉县| 广宗县| 昂仁县| 永定县| 隆安县| 巴彦淖尔市| 盐边县| 民和| 瓮安县|