Spring除了支持Schema方式配置AOP,還支持注解方式:使用@AspectJ風格的切面聲明。
1 啟用對@AspectJ的支持
Spring默認不支持@AspectJ風格的切面聲明,為了支持需要使用如下配置:

這樣Spring就能發現@AspectJ風格的切面並且將切面應用到目標對象。
2 聲明切面
@AspectJ風格的聲明切面非常簡單,使用@Aspect注解進行聲明:

然后將該切面在配置文件中聲明為Bean后,Spring就能自動識別並進行AOP方面的配置:
該切面就是一個POJO,可以在該切面中進行切入點及通知定義
聲明切面也可以直接使用注解的方式如下圖:

用@component 把普通pojo實例化到spring容器中。在去上圖xml文件中去配置。
1

2

3 聲明切入點
@AspectJ風格的命名切入點使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必須是返回void類型)實現。

value:指定切入點表達式;
argNames:指定命名切入點方法參數列表參數名字,可以有多個用“,”分隔,這些參數將傳遞給通知方法同名的參數,同時比如切入點表達式“args(param)”將匹配參數類型為命名切入點方法同名參數指定的參數類型。
pointcutName:切入點名字,可以使用該名字進行引用該切入點表達式。

定義了一個切入點,名字為“beforePointcut”,該切入點將匹配目標方法的第一個參數類型為通知方法實現中參數名為“param”的參數類型。
4 聲明通知
@AspectJ風格的聲明通知也支持5種通知類型:
一、前置通知:使用org.aspectj.lang.annotation 包下的@Before注解聲明;

value:指定切入點表達式或命名切入點;
argNames:與Schema方式配置中的同義。
示例:
1、定義接口和實現


2、定義切面:(打印日志的切面)

3、定義切入點:

4、定義通知:

完整的切面:

5、在spring_aop_annotation.xml配置文件中進行如下配置:

6、測試代碼TestSpringAopAnnotation.java

7、結果:

切面、切入點、通知全部使用注解完成:
(1)使用@Aspect將POJO聲明為切面;
(2)使用@Pointcut進行命名切入點聲明,同時指定目標方法第一個參數類型必須是java.lang.String,對於其他匹配的方法但參數類型不一致的將也是不匹配的,通過argNames = "param"指定了將把該匹配的目標方法參數傳遞給通知同名的參數上;
(3)使用@Before進行前置通知聲明,其中value用於定義切入點表達式或引用命名切入點;
(4)配置文件需要使用<aop:aspectj-autoproxy/>來開啟注解風格的@AspectJ支持;
(5)需要將切面注冊為Bean,如“aspect”Bean;
(6)測試代碼完全一樣。
上面我不僅演示了前置,還有后置一起演示了
二、后置返回通知:使用org.aspectj.lang.annotation 包下的@AfterReturning注解聲明;(也可以使用@After)

value:指定切入點表達式或命名切入點;
pointcut:同樣是指定切入點表達式或命名切入點,如果指定了將覆蓋value屬性指定的,pointcut具有高優先級;
argNames:與Schema方式配置中的同義;
returning:與Schema方式配置中的同義。
三、后置異常通知:使用org.aspectj.lang.annotation 包下的@AfterThrowing注解聲明;

value:指定切入點表達式或命名切入點;
pointcut:同樣是指定切入點表達式或命名切入點,如果指定了將覆蓋value屬性指定的,pointcut具有高優先級;
argNames:與Schema方式配置中的同義;
throwing:與Schema方式配置中的同義。
例子:

四、后置最終通知:使用org.aspectj.lang.annotation 包下的@After注解聲明;

value:指定切入點表達式或命名切入點;
argNames:與Schema方式配置中的同義;
示例:

五、環繞通知:使用org.aspectj.lang.annotation 包下的@Around注解聲明;

value:指定切入點表達式或命名切入點;
argNames:與Schema方式配置中的同義;
例子:

5 引入
@AspectJ風格的引入聲明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents聲明:

value:匹配需要引入接口的目標對象的AspectJ語法類型表達式;與Schema方式中的types-matching屬性同義;
private Interface interface:指定需要引入的接口;
defaultImpl:指定引入接口的默認實現類,沒有與Schema方式中的delegate-ref屬性同義的定義方式;
例子

