Spring除了支持Schema方式配置AOP,還支持註解方式:使用@AspectJ風格的切面聲明。java
<aop:aspectj-autoproxy/> spring
@AspectJ風格的聲明切面只須要使用@Aspect註解進行聲明,能夠在該切面中進行切入點及通知定義測試
@Aspect() spa
Public class Aspect{ ....}xml
將此切面聲明成Bean,<bean id="aspect" class="……Aspect"/> 接口
@AspectJ風格的命名切入點使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必須是返回void類型)實現。io
@Pointcut(value="切入點表達式", argNames = "參數名列表") class
public void pointcutName(……) {}import
argNames指定命名切入點方法參數列表參數名字,能夠有多個用「,」分隔,這些參數將傳遞給通知方法同名的參數,同時好比切入點表達式「args(param)」將匹配參數類型爲命名切入點方法同名參數指定的參數類型。配置
pointcutName:切入點名字,能夠使用該名字進行引用該切入點表達式。
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}
定義了一個切入點,名字爲「beforePointcut」,該切入點將匹配目標方法的第一個參數類型爲通知方法實現中參數名爲「param」的參數類型。
5種通知類型:前置通知,後置返回通知,後置異常通知,後置最終通知,環繞通知。
前置通知:@Before(value = "切入點表達式或命名切入點", argNames = "參數列表參數名")
一、定義接口和實現,在此咱們就使用Schema風格時的定義;
二、定義切面:
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class HelloWorldAspect2 { }
三、定義切入點:
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}
四、定義通知:
@Before(value = "beforePointcut(param)", argNames = "param")
public void beforeAdvice(String param) {System.out.println("====before advice param:" + param);}
五、xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy/>
<bean id="helloWorldService" class="cn.javass.spring.chapter6.service.impl.HelloWorldService"/> <bean id="aspect" class="cn.javass.spring.chapter6.aop.HelloWorldAspect2"/>
</beans>
總結:
切面、切入點、通知所有使用註解完成:
1)使用@Aspect將POJO聲明爲切面;
2)使用@Pointcut進行命名切入點聲明,同時指定目標方法第一個參數類型必須是java.lang.String,對於其餘匹配的方法但參數類型不一致的將也是不匹配的,經過argNames = "param"指定了將把該匹配的目標方法參數傳遞給通知同名的參數上;
3)使用@Before進行前置通知聲明,其中value用於定義切入點表達式或引用命名切入點;
4)配置文件須要使用<aop:aspectj-autoproxy/>來開啓註解風格的@AspectJ支持;
5)須要將切面註冊爲Bean,如「aspect」Bean;
6)測試代碼徹底同樣。
後置返回通知:
@AfterReturning(
value="切入點表達式或命名切入點",
pointcut="切入點表達式或命名切入點",
argNames="參數列表參數名",
returning="返回值對應參數名")
@AfterReturning(
value="execution(* cn.javass..*.sayBefore(..))",
pointcut="execution(* cn.javass..*.sayAfterReturning(..))",
argNames="retVal", returning="retVal")
public void afterReturningAdvice(Object retVal) {
System.out.println("=====after returning advice retVal:" + retVal);
}
其它代碼與前置通知同樣。
後置異常通知:
@AfterThrowing (
value="切入點表達式或命名切入點",
pointcut="切入點表達式或命名切入點",
argNames="參數列表參數名",
throwing="異常對應參數名")
@AfterThrowing(
value="execution(* cn.javass..*.sayAfterThrowing(..))",
argNames="exception", throwing="exception")
public void afterThrowingAdvice(Exception exception) {
System.out.println("====after throwing advice exception:" + exception);
}
後置最終通知:
@After (
value="切入點表達式或命名切入點",
argNames="參數列表參數名")
@After(value="execution(* cn.javass..*.sayAfterFinally(..))")
public void afterFinallyAdvice() {
System.out.println("====after finally advice");
}
環繞通知:
@Around (
value="切入點表達式或命名切入點",
argNames="參數列表參數名")
@Around(value="execution(* cn.javass..*.sayAround(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("===around before advice");
Object retVal = pjp.proceed(new Object[] {"replace"});
System.out.println("===around after advice");
return retVal;
}