Spring2.X以后,有許多東西得到了改進(jìn),對AOP的實(shí)現和設置也提供了新增了兩種方式:一種是基于XML Schema的設置;另一種是基于Annotation的支持。下面僅介紹注解的方式:
@Aspect
public class AdviceInterceptor {
@Pointcut("execution (* com.bhsc.AOP.target.*.*(..))")
// 聲明一個(gè)切入點(diǎn)(第一個(gè)*后要留一個(gè)空格)
private void anyMethod() {
}
@Before("anyMethod()")// 前置通知
public void before() {
System.out.println("前置通知");
}
@AfterReturning("anyMethod()")//后置通知
public void afterReturning(){
System.out.println("后置通知");
}
}
@Aspect表明這是一個(gè)切面,包括了通知和切入點(diǎn),Pointcut注解用來(lái)聲明一個(gè)切入點(diǎn),括號中的參數是切入點(diǎn)的表達式,這里的表達式的意思是對com.bhsc.AOP.target包下的所有方法進(jìn)行攔截。關(guān)于切入點(diǎn)表達式后面會(huì )有詳細的說(shuō)明。anyMethod是為切入點(diǎn)起一個(gè)名字,后面的“通知”都要依賴(lài)這個(gè)名字。
<!-- 開(kāi)啟切面編程功能,搜索所有帶有@Aspect注解的類(lèi),解析這個(gè)切面里的通知和切入點(diǎn)的定義 -->
<aop:aspectj-autoproxy />
<bean id="targetImple" class="com.bhsc.AOP.target.TargetImple" />
<bean id="theInterceptor"
class="com.bhsc.aop2.AdviceInterceptor" />
ApplicationContext ctx = new
ClassPathXmlApplicationContext("aop2.xml");
TargetInterface ti=(TargetInterface)
ctx.getBean("targetImple");
ti.hello("lisi");
ti.nihao("lisi");
前置通知
hello :lisi
后置通知
前置通知
你好 :lisi
后置通知
Pointcut表達式可以和Pointcut簽名一起定義,這樣,簽名就可以給多個(gè)通知使用,比如前面的anyMethod,后面的通知都用到了它,@Before("anyMethod()"),這里如果有多個(gè)簽名還可以使用&&,||等對簽名進(jìn)行操作。另外,也可以在通知上直接定義Pointcut表達式,還可以帶上JoinPoint參數,主要的目的是取得一些與JointPoint相關(guān)的信息,比如:
@Before("execution (* com.bhsc.AOP.target.*.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("前置通知");
System.out.println("目標對象:"+joinPoint.getTarget());
System.out.println("參數:"+joinPoint.getArgs().toString());
System.out.println("簽名信息::"+joinPoint.getSignature());
}
目標對象:com.bhsc.AOP.target.TargetImple@176cad3
參數:[Ljava.lang.Object;@1fe1feb
簽名信息:
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$MethodSignatureImpl@a084f8
其他通知
@After("anyMethod()")// 最終通知
public void after() {
System.out.println("最終通知");
}
@AfterThrowing("anyMethod()") // 例外通知
public void AfterThrowing() {
System.out.println("例外通知");
}
@Around("anyMethod()") //環(huán)繞通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("進(jìn)入環(huán)繞");
//if(){ // 進(jìn)行一些判斷,再執行環(huán)繞
Object result = pjp.proceed();
//}
System.out.println("退出環(huán)繞");
return result;
}
匹配參數和返回值
1.參數
@Before("anyMethod() && args(in)")// 前置通知
public void before(int in) {
System.out.println("前置通知");
System.out.println(in);
}
在前置通知的方法中有一個(gè)參數,然后再把此參數作為攔截條件(即是說(shuō)攔截帶有一個(gè)String類(lèi)型參數的方法)。args的名字和before方法參數名字相同
2.返回值,AfterReturn在有返回值的時(shí)候執行
@AfterReturning(pointcut ="anyMethod()",returning = "in")//后置通知
public void afterReturning(JoinPoint joinPoint,int in){
// System.out.println("目標對象:"+joinPoint.getTarget());
// System.out.println("參數:"+joinPoint.getArgs().toString());
// System.out.println("簽名信息::"+joinPoint.getSignature());
//
System.out.println("后置通知返回結果:"+in);
}
表達式切入點(diǎn)
1.格式:execution(返回值 空格 方法選擇)。兩部分組成,中間一定要有空格。
返回值:可以是*,說(shuō)明攔截任何方法。Java.lang.String(全名),攔截返回值為String類(lèi)型的方法。 常用的實(shí)例如下:
方法選擇:包名[類(lèi)名].*()。設定要攔截的方法簽名。
| 表達式(省略execution) | 說(shuō)明 |
| (java.lang.String 方法選擇略) | 攔截返回值為String類(lèi)型的方法 |
| (!void 方法選擇略) | 攔截返回值非空的方法 |
| (* com.asm..*.*(..)) | 攔截com.asm包及子包下每個(gè)類(lèi)的全部方法 |
| (* com.asm.*.*(..)) | 攔截com.asm包下每個(gè)類(lèi)的全部方法 |
| (* com.asm.User.*(..)) | 攔截asm包下User類(lèi)的所有方法 |
| (* com.asm.User.* | 攔截User類(lèi)中第一個(gè)參數為String,后面參數任一的方法 |
| | |
| | |
聯(lián)系客服