淺談spring——註解配置(九)

spring定義一個切面是件麻煩的事情,需要實現專門的接口,還要進行一些較爲複雜的配置,有沒有較爲簡單的方法???

@AspectJ註解可以很容易定義一個切面,且不需要實現任何的接口。缺點是對JDK的版本有限制,要求是5.0以上

當然對於不足5.0的版本,可以通過Schema的配置定義切面,方便程度和@AspectJ相差無幾。


無論是基於XML配置的AOP還是基於@AspectJ註解的AOP,只是在表達方式有所不同,底層都是採用動態代理技術(JDK代理或CGLib代理)。


註解是代碼的附屬信息,它遵循一個原則:註解不能直接干擾程序代碼的運行,無論是增加或刪除註解,代碼都能正常運行。java語言解釋器會忽略這些註解,而由第三方工具對註解進行解析,從而達到間接控制程序代碼的運行,它們通過java反射機制讀取註解的信息。


Pointcut和Advice分別表切點和增強,並用Advisor將兩者整體爲切面,@AspectJ則是採用註解的方式來描述切點、增強,兩者只是表述上有所不同,本質是一樣的。


代碼示例:

切面

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class PreGreetingAspect{
	@Before("execution(* greetTo(..))")
	public void beforeGreeting(){
		System.out.println("How are you");
	}
}
a.  PreGreetingAspect類定義處,標註了@Aspect註解,表示其爲一個切面。

b.  beforeGreeting方法上,Before表示是前置增強;execution(* greetTo(..))表示一個切點表達式,在目標類的greetTo()方法上織入增強,greetTo方法可以帶任意入參和任意返回值。

c.  beforeGreeting方法體,表示具體的橫切邏輯。

PreGreetingAspect類通過註解和代碼,將切點、增強類型、增強邏輯糅合到一個類中。


配置文件

 <aop:aspectj-autoproxy/>
	//目標bean
	<bean id="waiter" class="com.baobaotao.NaiveWaiter" />
	//採用@AspectJ註解的切面類
	<bean class="com.aspectj.example.PreGreetingAspect" />	
	//自動代理創建器,自動將@AspectJ切面類織入到目標Bean中
	<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>

AspectJ的切點表達式由關鍵字和操作參數組成。如execution(* greetTo(..))

execution爲關鍵字(ps:表示目標類執行某一方法)

* greetTo(..)爲操作參數(ps:表示目標方法的匹配模式串)


目前spring支持9個@AspectJ切點表達式函數,他們用不同的方式描述目標類的連接點,大致分爲4種類型:

1)方法切點函數:通過描述目標類方法信息定義連接點,如execution

2)方法入參切點函數:通過描述目標類方法入參的信息定義連接點

3)目標類切點函數:通過描述目標類類型信息定義連接點

4)代理類切點函數:通過描述目標類的代理類的信息定義連接點


增強類型:

@Before 前置增強

@AfterReturning 後置增強

@Around 環繞增強

@AfterThrowing 拋出異常的增強

@DeclareParents 引介增強

與xml形式的基本一致,只是換了種表達方式,採用了註解的形式來描述。


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

對於不滿足JDK5.0的項目,只能望@AspectJ而興嘆了。沒關係,我們還可以用Schema配置切面

說白了,其實就是將註解信息移到了Schema的XML配置文件中,形式不同罷了。


簡單實例:

xml配置文件

<aop:config proxy-target-class="true">
		//增強方法所在的bean
		<aop:aspect ref="adviceMethods">
			//前置增強
			<aop:before method="preGreeting"
				//切點表達式,與@AspectJ的語法相同
				pointcut="target(com.baobaotao.NaiveWaiter) and args(name)"
				arg-names="name" />
			//後置增強
			<aop:after-returning method="afterReturning"
				pointcut="target(com.baobaotao.SmartSeller)" returning="retVal" />
		</aop:aspect>
	</aop:config>
	<bean id="adviceMethods" class="com.baobaotao.schema.AdviceMethods" />
	<bean id="naiveWaiter" class="com.baobaotao.NaiveWaiter" />
	<bean id="naughtyWaiter" class="com.baobaotao.NaughtyWaiter" />
	<bean id="seller" class="com.baobaotao.SmartSeller" />

其中

1、 <aop:aspect>元素定義切面,內部可以定義多個增強

2、 <aop:config>擁有一個proxy-target-class屬性,true時表示聲明的切面採用CGLib動態代理技術;反之表示使用JDK動態代理技術


增強類:AdviceMethods

public class AdviceMethods {
	public void preGreeting(String name) {
		System.out.println("--how are you!--");
		System.out.println(name);
	}

    //後置增強對應方法
	public void afterReturning(int retVal){
	   System.out.println("----afterReturning()----");
	   System.out.println("returnValue:"+retVal);
	   System.out.println("----afterReturning()----");
	}

}


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