AOP(XML)【理解】【應用】【重點】

1.AOP基礎實例

A.導入jar包

核心包(4個) 日誌(2個) AOP(4個)

Spring進行AOP開發(1個)(3.2資源包)

spring-aop-3.2.0.RELEASE.jar

Spring整合AspectJ框架(3.2資源包)

spring-aspects-3.2.0.RELEASE.jar

AOP聯盟規範(1個) (3.0.2依賴包)

com.springsource.org.aopalliance-1.0.0.jar

aspectJ支持(1個) (3.0.2依賴包)

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

B.製作目標對象類(配置成Bean)

public class UserImpl {

//當前類的三個方法中具有共性功能System.out.println("共性功能1"); 抽取出來 public void add(){

//共性功能1被抽取走了,放入到了MyAdvice類中的functionOne方法裏 System.out.println("共性功能2");

System.out.println("user add....");

}

}

注意:共性功能被抽取後,不是在原始位置進行調用,而是將共性功能刪除

C.將抽取的功能製作成通知(配置成Bean)

public class MyAdvice {

//被抽取的共性功能1

public void functionOne(){

System.out.println("共性功能1");

}

}

說明:被抽取的共性功能製作成獨立的類中方法。由於要將兩個對象中的內容融合,Spring在控 制其融合的過程必須控制兩個對象,因此需要分別將兩個類配置爲Spring管理的Bean

D.開啓AOP空間的支持

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd

">

E.配置AOP的切面

<!-- 配置AOP -->

<aop:config>

<!-- 配置切面,指定切面類的Bean:配置切入點與通知之間的關係 --> <!-- ref:配置切面對應的Bean --> <aop:aspect ref="myAdvice"> <!-- 聲明通知的類別是何種類型 前置通知--> <!-- 配置前置通知 --> <!-- aop:before表示在原始方法執行前追加功能 --> <!-- pointcut:配置Spring監控的方法切入點 --> <!-- method:配置的切面類中對應的共性功能-方法名稱 --> <aop:before pointcut="execution(* cn.itcast.aop.one.UserImpl.add())" method="functionOne"/> </aop:aspect> </aop:config> F.製作Spring格式的客戶端程序測試 ApplicationContext ctx = new ClassPathXmlApplicationContext(“applicationContext.xml”); UserDao dao = (UserDao)ctx.getBean(“userDao”); dao.add(); 2.切入點表達式 格式:execution(切入點表達式) execution([方法的訪問控制修飾符] 方法的返回值 包名.類名/接口名.方法名(參數)) 注意:方法的訪問控制修飾符可以省略 範例: public void cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO類的無參數無返回值的add方法 void cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO類的無參數無返回值的add方法 方法的返回值可以寫具體的返回值,或者寫*表示任意返回值 void cn.itcast.UserDAO.add()公共的cn.itcat包中的UserDAO類的無參數無返回值的add方法 * cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO類的無參數不限定返回值的add方法 包名,方法名 * cn.itcast.*.dao.UserDAO.add() cn包下的itcast包下的任意包下的dao包下的….. * cn.itcast..dao.UserDAO.add() cn包下的itcast包下的任意層包下的dao包下的….. * *..*.*() 任意包下的任意類中的任意方法 參數 add() 無參數 add(*) 一個參數 add(int) 一個int型參數 add(*,*) 兩個參數 add(*,int) 兩個參數,第一個任意,第二個int add(..) 任意參數 add(*,..) 至少一個參數 特殊格式: * cn.itcast.UserDAO.add(..) && args(int,int) 錯誤 * cn.itcast.UserDAO.add(..) && args(int,int) 正確 * cn.itcast.UserDAO.add(int,int) && args(a,b) 不常用,正確 * cn.itcast.UserDAO.add(int,int) && args(b,a) 不常用,正確 3.切入點配置方式

切入點配置時,可以設置切面間共享切入點,也可以設置切面內共享切入點,還可以設置局部切入點

格式一:配置在通知類別後面 <aop:before pointcut="execution(public void *..*.*Impl.a*())" …. 格式二:配置在某個切面中,在當前切面範圍內共享 <aop:aspect ref="myAdvice"> <!-- 配置同一個切面中使用的公共切入點 --> <aop:pointcut expression="execution(public void *..*.*Impl.a*())" id="pt2"/> <aop:before pointcut-ref="pt2" ….. 格式三:配置在AOP總配置中,在全部範圍內共享 <aop:config> <aop:pointcut expression="execution(public void *..*.*Impl.a*())" id="pt1"/> <aop:aspect ref="myAdvice"> <aop:before pointcut-ref="pt1"…… </aop:aspect> </aop:config> 範例: <aop:config> <!-- 所有切面共享的切入點 --> <aop:pointcut expression="execution(* cn.itcast..*Tar*.*())" id="pt"/> <aop:aspect ref="myAdvice"> <!-- 在一個切面內共享的切入點:配置獨立的切入點表達式對象 --> <aop:pointcut expression="execution(* cn.itcast..*Tar*.*(..))" id="pt1"/> <aop:before pointcut-ref="pt" method="fn"/> <aop:before pointcut="execution(* *..*.*(..))" method="fn"/> </aop:aspect> <aop:aspect ref="myAdvice"> <!-- 配置獨立的切入點表達式對象 --> <aop:pointcut expression="execution(* cn.itcast..*Tar*.*(..))" id="pt2"/> <aop:before pointcut-ref="pt" method="fn"/> <aop:before pointcut-ref="pt" method="fn"/> </aop:aspect> </aop:config> 4.通知類別 通知共有五種類別 before:在原始操作前運行 after: 在原始操作後運行,無論方法是否拋出異常 afterReturning:在原始操作後運行,只有方法正常結束才運行,拋出異常則不運行 afterThrowing:在原始操作中如果拋出異常,運行 around: 在原始操作前後運行,通過ProceedingJoinPoint對象調用procee()方法完成對原始操作的調用 //環繞通知

public void around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("around before......");

//調用原始方法

pjp.proceed();

System.out.println("around after......");} 通知的配置格式 <aop:before pointcut-ref="pt2" method="before"/> <aop:after pointcut-ref="pt2" method="after"/> <aop:after-returning pointcut-ref="pt2" method="afterReturning"/> <aop:after-throwing pointcut-ref="pt2" method="afterThrowing"/> <aop:around pointcut-ref="pt2" method="around"/> 5.通知順序 在切入點之前運行的通知 執行允許與配置順序有關,在上面的先運行 在切入點之後運行的通知 在同一個切面中 執行允許與配置順序有關,在上面的先運行 在不同的切面中 執行允許與配置順序有關,與切面的配置順序相反 總結:不同通知類型執行的順序以配置順序爲準 6.獲取通知參數 爲環繞通知之外的通知方法定義形參JoinPoint,該參數必須是通知方法的第一個參數 獲取參數:Obejct[] args = jp.getArgs(); 範例: public void before(JoinPoint jp){ Object[] objs = jp.getArgs(); System.out.println("before......"+objs[0]+","+objs[1]); } 爲環繞通知方法定義形參ProceedingJoinPoint對象 獲取參數:Obejct[] args = pjp.getArgs(); 7.獲取通知返回值 afterReturning 與 around可以獲取方法的返回值 A.around通知獲取返回值 ProceedingJoinPoint對象執行調用原始操作的返回值就是原始方法的運行返回值 Object res = pt.proceed(args); 注意:如果原始方法返回值爲void類型,則around方法返回值設置爲Object 如果原始方法返回值爲非void類型,則around方法內必須將原始方法調用的結果返回 原始方法返回值爲void類型的,通知內獲取的返回值統一爲null public Object around(ProceedingJoinPoint pjp) throws Throwable{ Object res = pjp.proceed(args); return res; } B.afterReturning通知獲取返回值 在通知方法的參數中,聲明一個Object類型的參數,用於保存方法的返回值 public void afterReturning(JoinPoint jp,Object abc){ System.out.println("afterReturning......"+ abc); } 在配置文件中,爲afterReturning聲明保存返回值的變量名

<aop:after-returning method="afterReturning" returning="abc"/> 8.獲取通知異常對象 異常對象的獲取方式與返回值很相似,聲明變量,在配置中聲明保存異常對象的變量名 <aop:after-throwing pointcut-ref="pt" method="afterThrowing" throwing="e"/> public void afterThrowing (Throwable e){ System.out.println("afterThrowing......."+ e); }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章