当前位置: 首页 > article >正文

Spring07——AOP通知以及几个相关案例

切入点表达式 

注意,不是参数,是参数类型

可以使用通配符描述切入点,快速描述

■ *:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的通配符出现

execution(public∗com.itheima.∗.UserService.find(∗))

匹配com.itheima包下的任意类中的UserService类接口中所有find开头的带有一个参数的方法

■ ... :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

execution(publicUsercom..UserService.findById(..))

匹配com包下的任意包中的UserService类或接口中所有名为findById的方法

■ +:专用于匹配子类类型

execution(∗.∗.Service+..(∗..))

书写技巧

  1. 所有代码按照标准规范开发,否则以下技巧全部失效
  2. 描述切入点通常描述接口,而不描述实现类
  3. 访问控制修饰符对接口的开发采用public修饰
  4. 返回值类型对于增删改查类使用精确型匹配(可省略访问控制修饰符描述)
  5. 包含书签是尽量不使用..匹配,效率较低,常常做单个匹配或精确匹配
  6. 接口名称/类名名称与模块相关的最好采用..匹配,例如UserService书写为*Service,绑定业务层接口名称
  7. 方法名称书写以动词开头清晰匹配,例如采用..匹配,可以采用书写如getBy或.selectAll书写为selectAll
  8. 参数则较为复杂,根据具体方法灵活调整
  9. 通常不使用异常作为..匹配规则

AOP通知类型

@Around通知(用的最多)

@Pointcut("execution(* com.itheima.dao.BookDao.save())")
private void pointcut() {} // 切入点方法(save),具体实现为空
// 使用@Around注解定义一个环绕通知,用于在目标方法执行前后添加自定义逻辑  
@Around("pointcut()") // pointcut()是切入点表达式,指定在哪些方法上应用此通知  
public void way(ProceedingJoinPoint pjp) throws Throwable {  
    // 在目标方法执行前的逻辑  
    System.out.println("执行前");  
    
    // 执行目标方法  
    pjp.proceed(); // pjp.proceed()调用目标方法,允许原始方法继续执行  
    
    // 在目标方法执行后的逻辑  
    System.out.println("执行后");  
}

返回Int的@Around通知

// 定义一个切入点,匹配com.itheima.dao.BookDao类中的select()方法
@Around("execution(int com.itheima.dao.BookDao.select(int))")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // 方法执行前的逻辑
        System.out.println("Before method: " + joinPoint.getSignature());

        // 调用目标方法并获取返回值
        Integer result = (Integer) joinPoint.proceed();

        // 方法执行后的逻辑
        System.out.println("After method: " + joinPoint.getSignature());
        System.out.println("Method returned: " + result);

        return result; // 返回目标方法的结果
    }

上面的定义切入点可以直接用@Around声明。

如果切点函数的返回值为int或其他类型,强转为Integer(在函数前面限定返回值为Object)那么接收再最后return

@AfterReturning:没有抛异常才会最后执行,可以访问方法的返回值。适合于记录成功操作的日志或修改返回结果。

@AfterThrowing:在目标方法抛出异常后执行通知,可以用于异常处理和错误记录。

案例:模拟测量运行10000次时间

@Around("execution(* com.itheima.mapper.UserMapper.SelectStudentById(int))") // 修改为匹配所有方法
    public void testtime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis(); // 记录开始时间

        // 执行目标方法 10,000 次
        int iterations = 10000;
        for (int i = 0; i < iterations; i++) {
            // 调用目标方法并获取返回值
            joinPoint.proceed();
        }

        long endTime = System.currentTimeMillis(); // 记录结束时间
        long totalTime = endTime - startTime; // 计算总时间

        // 输出总时间
        System.out.println(joinPoint.getSignature() + "Total time for " + iterations + " executions: " + totalTime + " ms");

         // 或者返回某个结果
    }
@Test
    public void TestSelectStudentById(){
        User user = userMapper.SelectStudentById(2);
    }

AOP通知获取参数 

// 没有返回值的方法
@Before("pt()")
public void before(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println(Arrays.toString(args));
}
// 有返回值的方法
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
System.out.println(Arrays.toString(args));
Object ret = pjp.proceed();
return ret;
}

抛出异常了解一下 

案例:百度网盘密码格式处理

 问题引入

@Around("DataAdvice.servicePt()")
public Object trimString(ProceedingJoinPoint pjp) throws Throwable {
    Object[] args = pjp.getArgs();
    // 对原始参数的每一个参数进行操作
    for (int i = 0; i < args.length; i++) {
        // 如果是字符串数据
        if (args[i].getClass().equals(String.class)) {
            // 取出数据,trim()操作后,更新数据
            args[i] = args[i].toString().trim();
        }
    }
    return pjp.proceed(args);
}

http://www.kler.cn/a/428925.html

相关文章:

  • C++的auto_ptr智能指针:从诞生到被弃用的历程
  • 【Linux系统编程】—— 深度解析进程等待与终止:系统高效运行的关键
  • 以租赁合同的例子讲清楚 开源协议原理和区别
  • 【线性代数】行列式的概念
  • 【多线程】线程池
  • 锐捷路由器网关RG-NBR6135-E和锐捷交换机 Ruijie Reyee RG-ES224GC 电脑登录web方法
  • 4.4 可靠传输的工作原理
  • 自然语言处理的未来愿景
  • 【Nacos03】消息队列与微服务之Nacos 集群部署
  • Android 还在使用LogCat打日志?XLog框架;日志打印到控制台,打印到文件中。
  • ES(elasticsearch)整合Spring boot使用实例
  • C—初阶结构体
  • 第23周:机器学习及文献阅读
  • 【postgresql初级使用】在表的多个频繁使用列上创建一个索引,多条件查询优化,多场景案例揭示索引失效
  • WEB_星河飞雪_Windows(全)
  • HCIA-Access V2.5_2_2网络通信基础_TCP/IP模型结构
  • Unity引擎UI滚动列表——滚动复用基础介绍
  • Javascript Clipper library, v6(介绍目录)
  • 六、隐语PIR功能及使用介绍
  • 漫画之家:基于Spring Boot的漫画社交网络平台
  • C# WPF抽奖程序
  • 如何在UI自动化测试中创建稳定的定位器?
  • 笔记:在WPF中BitmapSource都有哪些派生类,他们主要功能,使用方法,使用场景
  • SpringBoot实现前后端传输加密设计
  • php项目的sdk封装成composer包的创建与发版
  • 【光电融合集成电路制造与封测】第四讲:扩散工艺,扩散的类型,恒定表面源扩散,限定表面源扩散,硼扩散