Spring的AOP模塊_第1頁(yè)
Spring的AOP模塊_第2頁(yè)
Spring的AOP模塊_第3頁(yè)
Spring的AOP模塊_第4頁(yè)
Spring的AOP模塊_第5頁(yè)
已閱讀5頁(yè),還剩12頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第3章 Spring的AOP模塊本章學(xué)習(xí)目的和要求本章重點(diǎn)和難點(diǎn)AOP是Spring框架的另一個(gè)重要特征。AOP(Aspect Oriented Programming,面向切面編程)把一個(gè)業(yè)務(wù)流程分成幾部分,例如權(quán)限檢查、業(yè)務(wù)處理、日志記錄,每個(gè)部分單獨(dú)處理,然后把它們組裝成完整的業(yè)務(wù)流程。每個(gè)部分被稱為切面(Aspect)或者關(guān)注點(diǎn)。3.1 實(shí)例:使用攔截器攔截方法(在struts-2.3.8中復(fù)制commons-logging-1.1.1、aopalliance-1.0.jar)AOP有一些重要的概念,包括切面(Aspect)、連接點(diǎn)(Joinpoint)、通知(Advice)、切入點(diǎn)(

2、Pointcut)、引用(Introduction)等。這些概念并不是Spring定義的。對(duì)于剛剛接觸AOP的開(kāi)發(fā)者來(lái)說(shuō),這些概念非常抽象,往往很難理解。拋開(kāi)這些抽象的概念,先來(lái)看一個(gè)AOP例子。前面的章節(jié)中曾介紹了一個(gè)AOP的例子。下面看一下稍微復(fù)雜的例子。本例中,AOP的規(guī)則要稍微復(fù)雜一些。3.1.1 Service接口Spring推薦使用接口編程。該接口定義了兩個(gè)方法。一會(huì)兒將使用攔截器攔截其中的withAop()方法,而另一個(gè)方法withoutAop()將不會(huì)被攔截。IAopService.javapackage com.helloweenvsfei.spring.aop;public

3、 interface IAopService/Service接口,定義兩個(gè)方法public void withAop() throws Exception;/將會(huì)被攔截public void withoutAop() throws Exception; /不會(huì)被攔截3.1.2 Service實(shí)現(xiàn)代碼IAopService實(shí)現(xiàn)類(lèi)中定義了一個(gè)name屬性,以及對(duì)應(yīng)的getter、setter方法。實(shí)現(xiàn)類(lèi)代碼為:AopServiceImpl.javapackage com.helloweenvsfei.spring.aop;import javax.security.auth.login.Accou

4、ntException;public class AopServiceImpl implements IAopService/Service實(shí)現(xiàn)private String name;/name屬性public void withAop() throws Exception/withAop方法實(shí)現(xiàn)System.out.println("有AOP的函數(shù)運(yùn)行。name: "+name);if (name.trim().length()=0)/ 如果name為空throw new AccountException("name屬性不能為空"); / 則拋出異常p

5、ublic void withoutAop() throws Exception/ withoutAop方法實(shí)現(xiàn)System.out.println("沒(méi)有AOP的函數(shù)運(yùn)行。");public String getName()/getter方法return name;public void setName(String name)/setter方法=name;3.1.3 方法前攔截器檢查name是否為null下面是方法前攔截器,實(shí)現(xiàn)自MethodBeforeAdvice接口。方法前攔截器在執(zhí)行指定方法前被調(diào)用,參數(shù)分別為被調(diào)用的方法、執(zhí)行時(shí)被傳入的參數(shù)、被

6、攔截的Bean。代碼為:MethodBeforeInterceptor.javapackage com.helloweenvsfei.spring.aop;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class MethodBeforeInterceptor implements MethodBeforeAdvice/方法前攔截器/ 調(diào)用對(duì)象的方法前將執(zhí)行該方法。參數(shù)分別為被調(diào)用的方法、被調(diào)用調(diào)用方法的參數(shù)、對(duì)象public void before(Method

7、 method, Object args, Object instance) throws ThrowableSystem.out.println("即將要執(zhí)行方法:" + method.getName();/ 打印控制臺(tái)if(instance instanceof AopServiceImpl)/如果是ServiceString name=(AopServiceImpl) instance).getName();/ 獲取nameif(name=null)/ 檢查是否為空throw new NullPointerException("name屬性不能為null&q

8、uot;);3.1.4 返回后攔截器輸出返回值返回后攔截器,實(shí)現(xiàn)自AfterReturningAdvice接口。返回后攔截器在執(zhí)行完指定方法、并返回之后被調(diào)用。如果有返回值,可以取到返回值,否則為null。參數(shù)分別為方法返回值、被調(diào)用的方法、執(zhí)行時(shí)被傳入的參數(shù)、被攔截的Bean。代碼為:MethodAfterInterceptor.javapackage com.helloweenvsfei.spring.aop;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public

9、class MethodAfterInterceptor implements AfterReturningAdvice/方法后攔截器public void afterReturning(Object value, Method method, Object args,Object instance) throws ThrowableSystem.out.println("方法"+method.getName()+"運(yùn)行完畢,返回值為:"+value);3.1.5 異常攔截器捕獲異常異常拋出攔截器,實(shí)現(xiàn)自ThrowsAdvice接口。如果指定的方法中有異

10、常被拋出,被調(diào)用。與上兩個(gè)攔截器接口不同,ThrowsAdvice接口沒(méi)有定義任何方法,因此不需要實(shí)現(xiàn)任何方法。但是如果定義了形如afterThrowing(Method,args,target,subclassOfThrowable)的方法,這些方法將會(huì)被調(diào)用。參數(shù)分別為:被調(diào)用的方法、方法的參數(shù)、被攔截的Bean以及拋出的異常類(lèi)。這里面只有最后一個(gè)參數(shù)是必須的。Spring之所以這樣設(shè)計(jì),是為了是開(kāi)發(fā)者靈活的定義多個(gè)方法捕捉不同的異常。代碼為:package com.helloweenvsfei.spring.aop;import java.lang.reflect.Method; imp

11、ort javax.security.auth.login.AccountException;import org.springframework.aop.ThrowsAdvice;public class ThrowsInterceptor implements ThrowsAdvice/異常攔截器public void afterThrowing(Method method, Object args, Object instance,AccountException ex) throws ThrowableSystem.out.println("方法"+method.g

12、etName()+" 拋出了異常:"+ex);public void afterThrowing(NullPointerException ex) throws ThrowableSystem.out.println("拋出了異常:" + ex);3.1.6 攔截器配置然后把三個(gè)攔截器連同Service實(shí)現(xiàn)類(lèi)配置到Spring中。Spring將實(shí)例化三個(gè)攔截器對(duì)象、一個(gè)Service對(duì)象,并安裝指定的規(guī)則裝配。配置代碼為:ApplicationContext.xml<?xml version="1.0" encoding=&qu

13、ot;UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans-2.0.xsd"><!-攔截

14、器 在withAop()方法前運(yùn)行-><bean id="aopMethodBeforeInterceptor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"><property name="advice"><bean class="com.helloweenvsfei.spring.aop.MethodBeforeInterceptor" /></property>

15、<property name="mappedName" value="withAop"></property></bean><!- 攔截器 在 withAop() 返回后運(yùn)行 -><bean id="aopMethodAfterInterceptor"class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"><property name="advice&qu

16、ot;><bean class="com.helloweenvsfei.spring.aop.MethodAfterInterceptor" /></property><property name="mappedName" value="withAop"></property></bean><!- 攔截器 在異常拋出后運(yùn)行 -><bean id="aopThrowsInterceptor"class="org.spring

17、framework.aop.support.NameMatchMethodPointcutAdvisor"><property name="advice"><bean class="com.helloweenvsfei.spring.aop.ThrowsInterceptor" /></property><property name="mappedName" value="withAop"></property></bean>&

18、lt;bean id="aopService"class="org.springframework.aop.framework.ProxyFactoryBean"><!- 攔截器 -><property name="interceptorNames"><list><value>aopMethodBeforeInterceptor</value><value>aopMethodAfterInterceptor</value><value>

19、;aopThrowsInterceptor</value></list></property><!- 被攔截的對(duì)象 -><property name="target"><bean class="com.helloweenvsfei.spring.aop.AopServiceImpl"><property name="name" value="Helloween"></property></bean></

20、property></bean></beans>3.1.7 運(yùn)行代碼運(yùn)行代碼從Spring容器中獲取Service對(duì)象,并分別執(zhí)行Service的兩個(gè)方法withAop()與withoutAop()。Spring將會(huì)在withAop()方法前后添加攔截器,但withoutAop()方法前后不會(huì)。代碼為:AopRun.javapackage com.helloweenvsfei.spring.aop;import org.springframework.beans.factory.xml.XmlBeanFactory;import org.springframewo

21、rk.core.io.ClassPathResource;public class AopRunpublic static void main(String args) throws Exception XmlBeanFactory factory = new XmlBeanFactory(/獲取Factorynew ClassPathResource("applicationContext.xml");IAopService hello = (IAopService) factory.getBean("aopService");/ 查找對(duì)象hello.

22、withAop();/ 執(zhí)行withAop()hello.withoutAop();/ 執(zhí)行withoutAop()factory.destroySingletons();/ 銷(xiāo)毀對(duì)象運(yùn)行效果如圖3.1。圖3.1 攔截器運(yùn)行效果在本例中,由于沒(méi)有異常拋出,因此ThrowsInterceptor沒(méi)有起作用。讀者可以在xml中設(shè)置name屬性為null或者空字符串,使withAop()方法中拋出異常,觀察運(yùn)行效果。3.2 攔截器與Filter的區(qū)別Spring的攔截器與Servlet的Filter有相似之處,比如二者都是AOP編程思想的體現(xiàn),都能實(shí)現(xiàn)權(quán)限檢查、日志記錄等。不同的是:3.2.1 使用

23、范圍不同F(xiàn)ilter是Servlet規(guī)范規(guī)定的,只能用于Web程序中。而攔截器即可以用于Web程序,也可以用于Application、Swing程序中。3.2.2 規(guī)范不同F(xiàn)ilter是在Servlet規(guī)范中定義的,是Servlet容器支持的。而攔截器是在Spring容器內(nèi)的,是Spring框架支持的。3.2.3 使用的資源不同同其它的代碼塊一樣,攔截器也是一個(gè)Spring的組件,歸Spring管理,配置在Spring文件中,因此能使用Spring里的任何資源、對(duì)象,例如Service對(duì)象、數(shù)據(jù)源、事務(wù)管理等,通過(guò)IoC注入到攔截器即可;而Filter則不能。3.2.4 深度不同F(xiàn)ilter在

24、只在Servlet前后起作用。而攔截器能夠深入到方法前后、異常拋出前后等,因此攔截器的使用具有更大的彈性。因此在Spring構(gòu)架的程序中,要優(yōu)先使用攔截器。3.3 AOP的相關(guān)概念看一下面向切面的編程的幾個(gè)常用的概念:切面Aspect、通知Advisor與切入點(diǎn)Pointcut。3.3.1 切面Aspect在本例中,方法withAop()、withoutAop()中都有一些代碼。雖然只是一些輸出語(yǔ)句,但是在真實(shí)的程序中這里應(yīng)該是一些有意義的代碼(如讀寫(xiě)數(shù)據(jù)庫(kù)、權(quán)限檢查、異常情況記錄等)。這些代碼可以看作是AOP中的切面(Aspect)??梢詫⑶忻胬斫鉃槟K。3.2.2 通知Advisor本例的

25、三個(gè)攔截器都是實(shí)現(xiàn)自某個(gè)Advisor接口。從類(lèi)名上看就知道三個(gè)攔截器都是AOP中的通知(Advisor)。一旦Spring符合條件,就會(huì)派發(fā)出通知。與生活中的通知不同的地方在于,Spring中的通知是帶有執(zhí)行代碼的,實(shí)現(xiàn)某種功能。3.3.3 切入點(diǎn)Pointcut在配置攔截器的時(shí)候,xml中只配置了withAop()方法使用攔截器,而withoutAop()方法沒(méi)有配置攔截器。這種配置是借助于org.springframework.aop.support.NameMatchMethodPointcutAdvisor完成的。從類(lèi)名稱上看,這是一個(gè)切入點(diǎn)(Pointcut)。該類(lèi)對(duì)象能配置對(duì)哪些

26、方法使用攔截器,從哪個(gè)地方“切入”進(jìn)去。配置時(shí)可以使用通配符。該類(lèi)名上也帶有Advisor是因?yàn)樗怯猛ㄖˋdvisor)實(shí)現(xiàn)的。簡(jiǎn)單地說(shuō),“切入點(diǎn)”負(fù)責(zé)往“什么地方”插入代碼,而“通知”負(fù)責(zé)插入“什么代碼”。3.3.4 切入點(diǎn)配置方式Spring提供靈活的切入點(diǎn)配置方式。例如使用正則表達(dá)式。下面是Spring官方的一個(gè)使用正則表達(dá)式的例子。Spring接受Perl 5支持的正則表達(dá)式:<bean id="settersAndAbsquatulateAdvisor" class="org.springframework.aop.support.Regexp

27、MethodPointcutAdvisor"><!-切入點(diǎn)-> <property name="interceptor"> <ref local="beanNameOfAopAllianceInterceptor"/><!-攔截器-> </property> <property name="patterns"><!-正則表達(dá)式配置切入點(diǎn)-> <list> <value>.*get.*</value>&

28、lt;!-包含get的方法-> <value>.*absquatulate</value><!-包含absquatulate的方法-> </list> </property></bean>3.4 AOP的代理模式代理模式是Spring中常用的設(shè)計(jì)模式。Spring提供了幾個(gè)常用的代理類(lèi),例如普通的代理類(lèi)、事務(wù)代理類(lèi)等等。3.4.1 ProxyFactoryBean代理工廠對(duì)象上例配置AopServiceImpl時(shí)使用了org.springframework.aop.framework.ProxyFactoryBean類(lèi)。這是Spring內(nèi)置的代理類(lèi),引入了一個(gè)中間層,能夠創(chuàng)建不同類(lèi)型的對(duì)象。利用它可以實(shí)現(xiàn)任何形式的AOP。3.4.2 TransactionProxyFactoryBean事務(wù)代理工廠對(duì)象另一個(gè)很有用的代理類(lèi)是TransactionProxyFactoryBean,是ProxyFactoryBean的子類(lèi),常用在數(shù)據(jù)庫(kù)編程上。Spring利用TransactionProxyFactoryBean對(duì)事務(wù)進(jìn)行管理,在指定方法前利用AOP連接數(shù)據(jù)庫(kù)并開(kāi)啟事務(wù),然后在指定方法返回后利用AOP提交事務(wù)并斷開(kāi)數(shù)據(jù)庫(kù)。例如Spring寵物商店里的事務(wù)性配置:<bean

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論