栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot中使用Aop

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot中使用Aop

Aop 面向切面编程

文章目录
  • 一、Aop是什么?
  • 二、应用场景
  • 三、优缺点
  • 四、应用举例
  • 五、通知类型
  • 六、环绕通知
  • 七、注意


一、Aop是什么?

aop面向切面编程,是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
重点在于切面

二、应用场景

例如:日志记录,性能统计,安全控制,事务处理,异常处理可将日志记录,异常处理等代码从原程序中抽离出来,

三、优缺点
  1. 提高代码的可重用性
  2. 业务代码编码更简洁
  3. 业务代码维护更高效
  4. 业务功能拓展更便捷
四、应用举例

首先我们创建一个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 {
    
    // 表示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来获取目标方法的信息例如:方法名,参数等等
后置通知,在方法执行后执行,所以可以目标方法的信息,返回通知(能获得返回值)和后置通知(不能获得返回值)的区别就是能否获得返回值,

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/839401.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号