文章目录
一、Aop是什么?
二、应用场景
三、优缺点
- 提高代码的可重用性
- 业务代码编码更简洁
- 业务代码维护更高效
- 业务功能拓展更便捷
四、应用举例
首先我们创建一个java类,里面分别有加,减,乘,除四个方法
@Service
public class Calculate {
//加
public int add(int i,int j){
System.out.println("我是加法");
return i+j;
}
//减
public int sub(int i,int j){
System.out.println("我是减法");
return i-j;
}
//乘
public int mul(int i,int j){
System.out.println("我是乘法");
return i*j;
}
//除
public int div(int i,int j){
System.out.println("我是除法");
return i/j;
}
}
现在有一个需求就是打印每一个方法执行的时间,传统的思维可能就是在每一个方法上打印出时间
public class Calculate {
//加
public int add(int i,int j){
System.out.println("我是加法,执行时间"+ LocalDate.now());
return i+j;
}
//减
public int sub(int i,int j){
System.out.println("我是减法,执行时间"+ LocalDate.now());
return i-j;
}
//乘
public int mul(int i,int j){
System.out.println("我是乘法,执行时间"+ LocalDate.now());
return i*j;
}
//除
public int div(int i,int j){
System.out.println("我是除法,执行时间"+ LocalDate.now());
return i/j;
}
使用AOP来实现,首先定义一个切面类
@Aspect
@Component
public class AopConfig {
/**
* @param joinPoint
* @Before:前置通知
* value:切入点表达式 二者加起来构建成为一个切面
* JoinPoint:连接点:可以理解为两个圆形的切点,从这个切点就可以获取到当前执行的目标类及方法
* 前置通知和后置通知的参数的都是 JoinPoint, 前置后置通知都没有返回值
*/
// 表示service包下的所有类所有方法都执行该前置通知
@Before("execution(* com.example.demo.service.*.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("前置通知开始执行");
System.out.println(joinPoint.getSignature().getName()+"执行时间"+ LocalDate.now());
System.out.println("传入的参数是: " + Arrays.asList(joinPoint.getArgs()));
}
//后置通知
@After(value = "execution(* com.example.demo.service.*.*(..))")
public void after(JoinPoint joinPoint) {
System.out.println("后置通知执行");
}
}
执行效果如下
五、通知类型
六、环绕通知
@Around(value = "execution(* com.example.demo.service.*.*(..))")
public int myAround(ProceedingJoinPoint pJoinPoint){
String name = pJoinPoint.getSignature().getName();
Object[] args = pJoinPoint.getArgs();
//args[0]=10; //还可以改传入的参数
int result=0;
try {
System.out.println("执行前置通知"+name+"执行了,传入的参数是"+Arrays.asList(args));
//可以理解为目标方法
result = (int) pJoinPoint.proceed();
System.out.println("返回通知执行了,返回值是"+result);
} catch (Throwable e) {
System.out.println("异常通知执行了"+name+"出异常了,异常是"+e);
e.printStackTrace();
}finally {
System.out.println("后置通知执行了"+name+"结束了");
}
//必须要有返回值
return result;
}
执行结果
//与切入点相等 默认为public可以省略
@Pointcut("execution(* com.example.demo.service.*.*(..))")
public void a(){
}
@Before("a()")
public void start(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println(name+"开始了"+"传入的参数是"+Arrays.asList(args));
}