Spring:AOP面向切面案例讲解AOP核心概念

Spring的AOP,在不惊动(改动)原有设计(代码)的前提下,想给谁添加功能就给谁添加。这个也就是Spring的理念:

无入侵式/无侵入式

AOP中核心概念分别指的是什么?

  • 连接点
  • 切入点
  • 通知
  • 通知类
  • 切面
    下面以一个例子进行讲解,直接上代码:

1,配置依赖坐标

xml 复制代码
<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>6.1.14</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.4</version>
    </dependency>
  </dependencies>

2,定义接口与实现类

java 复制代码
//接口
public interface BookDao {
    public void save();

    public void update();

    public void delete();

    public void select();
}

//实现类
@Repository
public class BookDaoImpl implements BookDao {

    public void save() {
        //记录程序当前执行执行(开始时间)
        Long startTime = System.currentTimeMillis();
        //业务执行万次
        for (int i = 0;i<10000;i++) {
            System.out.println("book dao save ...");
        }
        //记录程序当前执行时间(结束时间)
        Long endTime = System.currentTimeMillis();
        //计算时间差
        Long totalTime = endTime-startTime;
        //输出信息
        System.out.println("执行万次消耗时间:" + totalTime + "ms");
    }

    public void update(){
        System.out.println("book dao update ...");
    }

    public void delete(){
        System.out.println("book dao delete ...");
    }

    public void select(){
        System.out.println("book dao select ...");
    }
}

3,定义通知类和通知、定义切入点、制作切面

java 复制代码
@Component
@Aspect
public class MyAdvice {

    @Pointcut("execution(* com.itheima.dao.BookDao.*d*(..))")
    private void pt(){}

    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("------------------------------");
        Long startTime = System.currentTimeMillis();
        for (int i = 0 ; i<10000 ; i++) {
            //调用原始操作
            pjp.proceed();
        }
        Long endTime = System.currentTimeMillis();
        Long totalTime = endTime-startTime;
        System.out.println("执行万次消耗时间:" + totalTime + "ms");
        return null;
    }

}

讲解:

  • Pointcut(切入点)
    @Pointcut("execution(* com.itheima.dao.BookDao.*d*(...))")
    这个注解定义了一个切入点,它匹配所有在com.itheima.dao.BookDao类中以d开头的方法的执行。
    这里的*表示返回类型可以是任何类型
    而(...)表示方法可以接受任意数量和类型的参数
    *d*中的第一个星号表示返回值类型不限,d之后的星号表示方法名中必须包含字母d,但是可以在其后有其他字符。
  • Around Advice(环绕通知)
    @Around("pt()")
    这个注解定义了一个环绕通知,它会在切入点匹配的方法被执行之前和之后执行。
    在这个环绕通知中,首先打印了一条分割线,然后记录了开始时间,接着在一个循环中调用了原始方法10000次(pjp.proceed()),最后计算并打印了这10000次调用所花费的时间。
  • ProceedingJoinPoint 是 AspectJ 框架中的一个接口,用于表示环绕通知(@Around)中的连接点(Join Point)。连接点是指程序执行过程中的某个特定点,例如方法的调用、异常的抛出等。在环绕通知中,ProceedingJoinPoint 对象提供了访问连接点信息和控制连接点执行的能力。
    主要功能和方法:
    获取连接点的信息:
    getSignature(): 返回连接点的签名,通常是一个方法签名。
    getArgs(): 返回连接点方法的参数数组。
    getTarget(): 返回目标对象,即被增强的对象。
    getThis(): 返回代理对象,即当前执行的代理对象。
    控制连接点的执行:
    proceed(): 执行连接点的方法。如果不调用这个方法,连接点的方法将不会被执行。
    proceed(Object[] args): 使用指定的参数数组重新执行连接点的方法。

4,核心配置类,开启注解格式AOP功能

java 复制代码
@Configuration
@ComponentScan("com.itheima")
@EnableAspectJAutoProxy
public class SpringConfig {
}

5,运行程序

java 复制代码
public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bookDao = ctx.getBean(BookDao.class);
        bookDao.select();
        //bookDao.delete();
        //bookDao.update();
        //bookDao.save();
    }
}

运行结果:

  • bookDao.select():并没有执行增强功能,因为@Pointcut("execution(* com.itheima.dao.BookDao.*d*(...))")中d 不包含select
  • bookDao.delete():执行了增强功能
  • bookDao.update():执行了增强功能
  • bookDao.save():同样没有执行增强功能,因为@Pointcut("execution(* com.itheima.dao.BookDao.*d*(...))")中d不包含save

示例讲解概念

(1)前面一直在强调,Spring的AOP是对一个类的方法在不进行任何修改的前提下实现增强。对于上面的案例中BookServiceImpl中有save,update,deleteselect方法,这些方法我们给起了一个名字叫连接点

(2)在BookServiceImpl的四个方法中,updatedelete只有打印没有计算万次执行消耗时间,但是在运行的时候已经有该功能,那也就是说updatedelete方法都已经被增强,所以对于需要增强的方法我们给起了一个名字叫切入点

(3)执行BookServiceImpl的update和delete方法的时候都被添加了一个计算万次执行消耗时间的功能,将这个功能抽取到一个方法中,换句话说就是存放共性功能的方法,我们给起了个名字叫通知

(4)通知是要增强的内容,会有多个,切入点是需要被增强的方法,也会有多个,那哪个切入点需要添加哪个通知,就需要提前将它们之间的关系描述清楚,那么对于通知和切入点之间的关系描述,我们给起了个名字叫切面

(5)通知是一个方法,方法不能独立存在需要被写在一个类中,这个类我们也给起了个名字叫通知类

至此AOP中的核心概念就已经介绍完了,总结下:

  • 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
    • 在SpringAOP中,理解为方法的执行
  • 切入点(Pointcut):匹配连接点的式子
    • 在SpringAOP中,一个切入点可以描述一个具体方法,也可也匹配多个方法
      • 一个具体的方法:如com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
      • 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
    • 连接点范围要比切入点范围大,是切入点的方法也一定是连接点,但是是连接点的方法就不一定要被增强,所以可能不是切入点
  • 通知(Advice):在切入点处执行的操作,也就是共性功能
    • 在SpringAOP中,功能最终以方法的形式呈现
  • 通知类:定义通知的类
  • 切面(Aspect):描述通知与切入点的对应关系。

[说明]:内容主要来源黑马程序员网上资源学习

相关推荐
s:10320 分钟前
【框架】参考 Spring Security 安全框架设计出,轻量化高可扩展的身份认证与授权架构
java·开发语言
南山十一少3 小时前
Spring Security+JWT+Redis实现项目级前后端分离认证授权
java·spring·bootstrap
闲猫5 小时前
go orm GORM
开发语言·后端·golang
427724005 小时前
IDEA使用git不提示账号密码登录,而是输入token问题解决
java·git·intellij-idea
丁卯4045 小时前
Go语言中使用viper绑定结构体和yaml文件信息时,标签的使用
服务器·后端·golang
chengooooooo5 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
李长渊哦5 小时前
常用的 JVM 参数:配置与优化指南
java·jvm
计算机小白一个5 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
Tirzano6 小时前
springsecurity自定义认证
spring boot·spring
南宫生8 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode