1. 程式人生 > >Spring的AOP配置詳解

Spring的AOP配置詳解

AOP是一種切面程式設計的思想,縱向抽取,橫向重複使其核心。Spring提供了對AOP程式設計的支援,原理是Spring在物件建立時可以動態生成代理物件,而且對這個物件的指定進行邏輯加強。下面說一下AOP怎麼寫在配置檔案中。

假設我們現在的需求是在操作資料庫的程式碼前後加上事務處理。

首先編寫目標物件類

public class UserServiceImpl implements UserService {
	@Override
	public void save() {
		System.out.println("儲存使用者!");
	}
	@Override
	public void delete() {
		System.out.println("刪除使用者!");
	}
	@Override
	public void update() {
		System.out.println("更新使用者!");
	}
	@Override
	public void find() {
		System.out.println("查詢使用者!");
	}
}

編寫通知類

public class MyAdvice {

	//前置通知
	public void before(){
		System.out.println("這是前置通知!!");
	}
	//後置通知
	public void afterReturning(){
		System.out.println("這是後置通知(如果出現異常不會呼叫)!!");
	}
	//環繞通知
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("這是環繞通知之前的部分!!");
		Object proceed = pjp.proceed();//呼叫目標方法
		System.out.println("這是環繞通知之後的部分!!");
		return proceed;
	}
	//異常通知
	public void afterException(){
		System.out.println("出事啦!出現異常了!!");
	}
	//後置通知
	public void after(){
		System.out.println("這是後置通知(出現異常也會呼叫)!!");
	}
}

配置檔案applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

<!-- 準備工作: 匯入aop(約束)名稱空間 -->
<!-- 1.配置目標物件 -->
	<bean name="userService" class="test.service.UserServiceImpl" ></bean>
<!-- 2.配置通知物件 -->
	<bean name="myAdvice" class="test_springaop.MyAdvice" ></bean>
<!-- 3.配置將通知織入目標物件 -->
	<aop:config>
		<!-- 配置切入點 -->
		<aop:pointcut expression="execution(* test.service.*ServiceImpl.*(..))" id="pc"/>
		<aop:aspect ref="myAdvice" >
			<!-- 指定名為before方法作為前置通知 -->
			<aop:before method="before" pointcut-ref="pc" />
			<!-- 後置 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pc" />
			<!-- 環繞通知 -->
			<aop:around method="around" pointcut-ref="pc" />
			<!-- 異常攔截通知 -->
			<aop:after-throwing method="afterException" pointcut-ref="pc"/>
			<!-- 後置 -->
			<aop:after method="after" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>
</beans>

開始配置

首先要匯入SpringAOP的名稱空間,然後把目標物件和通知類配置到配置檔案中,然後配置將通知織入到目標物件。在<config>的標籤下進行配置,先配置切入點<pointcut>,切入點是你想要增強和已經增強的方法,id屬性指定這個切點的一個名稱,expression屬性必須用表示式來寫,格式為execution(完整方法名),如(public void test.service.UserServiceImpl.save()),表示一個公用的返回值為void的方法save()作為想要增強的方法,public可以不寫,因為這是個預設值,而且增強private方法意義不太大。在表示式中,如果我們想一次對多個方法進行增強,可以用*代替一些文字,達到通配的效果,例如

     void test.service.UserServiceImpl.save():去掉public

    * test.service.UserServiceImpl.save():返回值任意

    * test.service.UserServiceImpl.*():返回值任意且對est.service.UserServiceImp類下所有空參方法進行增強。

    *test.service.*ServiceImpl.*(..):返回值任意且對est.service包中以ServiceImpl為結尾的類下所有方法(引數任意)增強。

    * test.service..*ServiceImpl.*(..):返回值任意且對est.service包和其子包中以ServiceImpl為結尾的類下所有方法(引數任意)增強。

然後配置<aspect>,其配置的主要目的是把通知織入切入點中,首先通過ref屬性引入配置好的通知類,然後通過三個引數確定要織入的物件和位置

aop:指定位置,有五個候選字 
      before:前置通知,目標方法執行之前呼叫
      alter-Returning:後置通知(如果出現異常不會呼叫),在目標方法執行之後呼叫
      around:環繞通知在目標方法之前和之後都呼叫
      after-throwing:異常攔截通知,如果出現異常,就會呼叫
      after:後置通知(無論是否出現 異常都會呼叫),在目標方法執行之後呼叫

method:選定要織入到切入點的通知類中的方法。(注:環繞通知的方法編寫時要確認環繞點)

pointcut-ref:選定切入點依賴物件,值為配置切入點時的id屬性。

這樣我們在獲取目標物件是,獲取到的就是Spring動態代理後進行增強過的代理物件。