【Spring】AOP實現及原理
阿新 • • 發佈:2020-09-08
5).Spring AOP程式設計:動態代理
(1)引言(靜態代理): 現有程式碼的問題: ①事務程式碼耦合: 現有的事務控制的程式碼,耦合在了service方法中,一旦資料庫訪問技術發生變化,所 有事務控制程式碼需要替換,導致service的程式碼被大量的修改 ②事務控制的程式碼冗餘: 大量相同的事務控制程式碼出現在了service方法中,出現冗餘程式碼,不利於後期的升級和維護 解決思路: 通過手動新增代理類,將事務控制程式碼放在代理類中 代理類的核心規範 · 靜態代理[重點] ① 先和目標類實現相同的介面 ② 將額外功能(事務控制),放在代理類中 ③ 呼叫目標物件的目標方法 ④ 代替目標物件接受呼叫 作用:將事務程式碼和service的核心功能程式碼解耦和 缺點:每個目標類都要書寫一個代理類,存在程式碼冗餘 (2)動態代理 動態代理: 使用技術動態為目標類生成代理類 代理類核心: ① 額外功能(事務控制等) ② 呼叫目標物件的方法 ③ 和目標類擁有相同的介面 Springaop技術的核心思想: ① 將額外功能的程式碼放在功能增強的物件中 ② Spring AOP技術,將功能增強中的額外功能的程式碼,動態生成代理類,新增進去 spring AOP的步驟: 準備: 匯入spring AOP依賴的jar(`asm.jar` `cglib.jar` `aspectj.awear.RELEASE.jar`) ①準備目標類(例如service) ②書寫額外功能所在的 功能增強類 public class 增強類 implements org.aopalliance.intercept.MethodInterceptor{ @Override public Object invoke(MethodInvocation mi) throws Throwable { //1. 開啟事務 //2. 呼叫目標物件的功能。 Object o = mi.proceed();//呼叫真正的目標物件的方法 //3. 提交事務 return o; } } ③通過aop技術,動態生成代理類 = 額外功能+目標物件 核心:① 額外功能加入的位置: 切入點,是告訴spring將額外功能程式碼放在哪個方法的內部[告訴spring將額外功能加入哪個類的哪個方法中② 組裝: 額外功能+類、方法(切入點)==代理類 例子: <!-- 1 管理目標物件UserServiceImpl --> <bean id="us" class="com.jwnming.UserServiceImpl"></bean> <!-- 2 管理增強類UserServiceImplZengqiang --> <bean id="zengqiang" class="com.jwnming.UserServiceImplZengqiang"></bean> <!-- 3 為us物件產生代理類,代理物件 :切入點、組裝--> <aop:config> <!-- 切入點:明確目標類和目標方法 --> <aop:pointcut id="pc" expression="execution(void com.jwnming.UserServiceImpl.regist())"></aop:pointcut> <!-- 組裝 --> <aop:advisor pointcut-ref="pc" advice-ref="zengqiang"></aop:advisor> </aop:config>
6).Spring AOP程式設計思想、MethodInterceptor介面詳解
(1)SpringAOP程式設計思想 AOP:aspect orinted programing 面向切面程式設計,在不修改目標的程式碼的情況下,動態的為目標類的方法新增額外的功能程式碼 本質:使用jdk技術,動態為目標類生成了代理類的,生成代理的物件,使用生成的代理物件替換了你的原始的目標物件 (2)MethodInterceptor詳解 public class XxxAdvice implements MethodInterceptor{ @Override public Object invoke(MethodInvocation mi) throws Throwable { //mi: 代表目標物件的方法 Object o = mi.proceed();//呼叫目標物件的目標方法 return o; } } ① 獲得目標物件的方法:mi.getMethod(); //Method 型別的目標方法 ② 目標物件:mi.getThis(); //獲得目標物件 ③ 獲得代理的目標方法的呼叫時,實際傳入的引數:mi.getArguments(); //陣列,實際傳入的引數 ④ 呼叫目標物件的目標方法:Object o = mi.proceed(); //us.regist() ps.add() 注:① 呼叫目標物件的方法 ② 返回值代表實際被代理的方法的返回值
7).Spring的<aop:pointcut>標籤幾種切入點表示式
切入點表示式詳解 pointcut切入點: 告訴spring功能增強的目標類的目標方法 標籤:<aop:pointcut id="" expression="切入點表示式"></aop:pointcut> (1)execution 特點: 精確到方法宣告的 ① 精確點指定包指定類指定方法。 execution(返回值 包名.子包.孫子包.類.方法名(引數1型別,引數2型別)); //引數型別之間用逗號隔開 ② 精確到指定包下的指定類的執行方法,引數任意: execution(返回值 包名.子包.孫子包.類.方法名(..)); ③ 精確到指定包的指定類,方法名任意,引數型別任意 execution(返回值 包名.子包.孫子包.類.*(..)); ④ 精確指定包下的任意類,任意方法,任意引數型別 execution(返回值 包名.子包.孫子包.*.*(..)); ⑤ 精確到指定包下的類,及其子包下的所有類的任意方法,任意引數,任意返回值型別 execution(* p1.p2.p3..*.*(..)); (2)within 語法: expression="within(表示式語法)" 特點: 表示式的寫法,只精確到類 ① 指定包下的類: within(包名.類名); ② 指定包及其子包下的所有類: within(p1.p2.p3..*); (3)@annotation 語法: expression="@annotation(註解全類名)" 特點: 凡是新增指定註解的方法,都會被功能增強 使用步驟: ① 定義註解:public @interface HeheAdvice { } //定義:添加了HeheAdvice註解的方法,都會被功能增強 ② 使用註解:給需要功能增強的方法添加註解,例a1方法 public class AServiceImpl{ @HeheAdvice public void a1(){} } ③ 通過切入點,指定:新增@HeheAdvice的方法,進行功能增強 <aop:pointcut id="" expression="@annotation(註解名的全類名)"></aop:pointcut>