您的位置:首页 > 编程语言 > Java开发

Spring中切点表达式的重用

2017-09-02 19:55 323 查看
Spring中切点表达式的重用

一、说在前面

从上面几篇文章的学习中,我们可以看到在对应通知的表单时总要指定execution(* *.*(..)),修改起来需要多次修改重复的地方,很麻烦。为了方便修改我们引入了@PointCut。

二、引入@Pointcut之后的代码

为了便于对比,在代码中只是将 未引用@Pointcut之前的代码注释掉。

ArithmeticCalculator接口及对应的实现类、applicationContext.xml配置文件、测试函数都和上篇文章中一模一样,在这里就不在赘述。

下面直接展示重用部分代码LoggingAspect类:

package com.at.aop;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
/*
* 切点表达式的重用:
* 定义一个方法,用于声明切入点表达式;一般情况下,改方法中不需要添加其他的代码。
* 使用 @Pointcut 来声明切入点表达式
* 后面的其他通知直接使用方法名来引入当前的切入点表达式
*/
@Pointcut("execution(* com.at.aop.ArithmeticCalculator.*(..))")
public void declareJoinPointExpression(){

}

//前置通知:在com.at.aop.ArithmeticCalculator 接口的实现类的每一个方法开始之前执行一段代码
//@Before("execution(public int com.at.aop.ArithmeticCalculator.*(..))")
@Before("declareJoinPointExpression()")
public void beforeMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("前置通知方法 "+methodName+" 开始 "+args);
}

//后置通知:在目标方法执行后(无论是否发生异常),执行的通知。
//在后置通知中还不能访问目标方法执行的结果。这个结果需要在返回通知中访问(下文讲)
//@After("execution(* com.at.aop.ArithmeticCalculator.*(..))")
@After("declareJoinPointExpression()")
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("后置通知方法 "+methodName+" 结束 ");
}

//返回通知:在代码正常执行之后返回的代码
//返回通知是可以访问到方法的返回值的。
//@AfterReturning(value="execution(* com.at.aop.ArithmeticCalculator.*(..))",returning="result")
@AfterReturning(value="declareJoinPointExpression()",returning="result")
public void afterReturning(JoinPoint joinPoint,Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("返回通知方法 "+methodName+" 结果为 "+result);
}

//异常通知
//@AfterThrowing(value="execution(* com.at.aop.ArithmeticCalculator.*(..))",throwing="ex")
@AfterThrowing(value="declareJoinPointExpression()",throwing="ex")
public void afterThrowing(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println("异常通知方法 "+methodName+" 发生的异常为 "+ex);
}

/*环绕通知需要携带 ProceedingJoinPoint 类型的参数
* 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是够执行目标方法
* 并且环绕通知必须有返回值,返回值就是目标方法的返回值。
*/
//@Around("execution(* com.at.aop.ArithmeticCalculator.*(..))")
@Around("declareJoinPointExpression()")
public Object aroundMethod(ProceedingJoinPoint pjp){

Object result = null;
String methodName = pjp.getSignature().getName();

try {
//前置通知
System.out.println("环绕通知中的前置通知方法 "+methodName+" 开始于参数 "+Arrays.asList(pjp.getArgs()));
//执行目标
result = pjp.proceed();
//返回通知
System.out.println("环绕通知中的返回通知方法 "+methodName+" 结果为 "+result);
} catch (Throwable e) {
//异常通知
System.out.println("环绕通知中的异常通知方法 "+methodName+" 结果为 "+e);
throw new RuntimeException(e);
}
//后置通知
System.out.println("环绕通知中的后置通知方法 "+methodName+" 结束了 ");

return result;
}
}


By luoyepiaoxue2014

微博地址: http://weibo.com/luoyepiaoxue2014 点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring AOP 重用