Spring除了支持XML方式配置AOP,還支持註解方式:使用@AspectJ風格的切面聲明。
但是用註解方式需要在XML啓用對@AspectJ的支持,將在Spring上下文創建一個AnnotationAwareAspectJAutoProxyCreator類,它會自動代理一些Bean,這些Bean的方法需要與使用@Aspect註解的Bena中所定義的切點相匹配,而這些切點又是使用@Pointcut註解定義出來的,下面來看下例子(PS:我的例子都沒有攜帶參數):
聲明切入點
@AspectJ風格的命名切入點使用org.aspectj.lang.annotation包下的@Pointcut方法(方法必須是返回void類型)實現。
@Pointcut(value=”切入點表達式”, argNames = “參數名列表”)
public void pointcutName(……) {}
聲明通知
前置通知
使用org.aspectj.lang.annotation 包下的@Before註解聲明;
@Before(value = “切入點表達式或命名切入點”, argNames = “參數列表參數名”)
後置返回通知
使用org.aspectj.lang.annotation 包下的@AfterReturning註解聲明;
@AfterReturning(
value=”切入點表達式或命名切入點”,
pointcut=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”,
returning=”返回值對應參數名”)
後置最終通知
使用org.aspectj.lang.annotation 包下的@After註解聲明;
@After (
value=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”)
後置異常通知
使用org.aspectj.lang.annotation 包下的@AfterThrowing註解聲明
@AfterThrowing (
value=”切入點表達式或命名切入點”,
pointcut=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”,
throwing=”異常對應參數名”)
[java]
package cn.com.ztz.spring.service;
public interface ShowService {
public void show();
}
[java]
package cn.com.ztz.spring.service;
public class ShowServiceImpl implements ShowService{
@Override
public void show() {
showBefore();
//showError();//異常測試 (後置異常通知)
showEnd();
}
public void showBefore(){
System.out.println("showBefore============");
}
public void showError(){
System.out.println("showError============");
throw new RuntimeException();
}
public void showEnd(){
System.out.println("showEnd===============");
}
}
[java]
package cn.com.ztz.spring.service;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AudienceAspect {
//定義切點
@Pointcut("execution(* cn.com.ztz.spring.service.ShowServiceImpl.show(..))")
public void performance(){
//該方法的內容不重要,該方法的本身只是個標識,供@Pointcut註解依附
}
//前置通知
@Before("performance()")
public void taskSeats(){
System.out.println("等候節目開始===");
}
//後置通知
@After("performance()")
public void applaud(){
System.out.println("鼓掌=========");
}
//後置異常通知
@AfterThrowing("performance()")
public void demandRefund(){
System.out.println("退錢離場======");
}
}
[html]
<!-- 啓用@AspectJ支持 -->
<aop:aspectj-autoproxy/>
<bean id="show" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
<bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
[java]
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ShowService hs = ctx.getBean("show", ShowService.class);
System.out.println("======================================");
hs.show();
System.out.println("======================================");
}
運行測試方法控制檯輸出:
======================================
等候節目開始===
showBefore============
showEnd===============
鼓掌 ========
======================================
註解環繞通知
像Spring基於XML的AOP一樣,@AspectJ註解的使用不僅只限定與定義前置和後置通知類型。我們還可以創建環繞通知,使用環繞通知需要使用@Around。
@Around (
value=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”)
[java]
public interface ShowService {
public void show(String param);
}
[java]
@Override
public void show(String param) {
System.out.println("around==========="+param);
}
[java]
@Aspect
public class AudienceAspect {
//定義切點
@Pointcut("execution(* cn.com.ztz.spring.service.ShowServiceImpl.show(..))")
public void performance(){
//該方法的內容不重要,該方法的本身只是個標識,供@Pointcut註解依附
}
@Around("performance()")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice===========");
Object retVal = pjp.proceed(new Object[] {"around"});
System.out.println("around after advice===========");
return retVal;
}
}
運行測試方法控制檯輸出:
======================================
around before advice===========
around===========around
around after advice===========
======================================
引入
@AspectJ風格的引入聲明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents聲明
@DeclareParents(
value=”AspectJ語法類型表達式”,
defaultImpl=”引入接口的默認實現類”)
[java]
package cn.com.ztz.spring.service;
public interface DeclareService {
public void declare();
}
[java]
package cn.com.ztz.spring.service;
public class DeclareServiceImpl implements DeclareService {
@Override
public void declare() {
System.out.println("declare=====================");
}
}
[java]
package cn.com.ztz.spring.service;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
@Aspect
public class AudienceAspect {
@DeclareParents(value="cn.com.ztz.spring.service.ShowServiceImpl+",
defaultImpl=cn.com.ztz.spring.service.DeclareServiceImpl.class)
private DeclareService declareService;}
[java]
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
DeclareService hs = ctx.getBean("show", DeclareService.class);
System.out.println("======================================");
hs.declare();
System.out.println("======================================");
}
運行測試方法輸出結果:
======================================
declare=====================
======================================