1. 程式人生 > 實用技巧 >【Spring】AOP實現及原理

【Spring】AOP實現及原理

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>