springboot中使用Aop

原文地址:https://blog.csdn.net/qq_44693065/article/details/124327021

一、Aop是什么?

aop面向切面编程,是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用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("后置通知执行");

}

}

执行效果如下

这里面的重点就是:execution(* com.example.demo.service..(…))

切入点表达式,值为方法的全名(返回值,包名,方法名,参数)spring容器可根据切入点表达式去找到需要切入的方法,上面这个表达式的意义就是表示service包下的所有类所有方法都执行该前置通知

五、通知类型

spring容器中共有五种通知类型

1 : 前置通知 @Before 在方法执行前执行

2:后置通知 @After 在方法执行后执行

3:返回通知 @AfterReturning在方法执行前执行,无论是否出现异常

4:异常通知 @AfterThrowing在方法执行前执行,出现异常则不执行

5:环绕通知 @Around可以单独完成以上四个通知

六、环绕通知

@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));

}

七、注意

前置通知和后置通知都可以通过JoinPoint joinPoint来获取目标方法的信息例如:方法名,参数等等

后置通知,在方法执行后执行,所以可以目标方法的信息,返回通知(能获得返回值)和后置通知(不能获得返回值)的区别就是能否获得返回值,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值