Spring关于Aop的详解

1.Aop的定义

AOP(面向切面编程)是一种编程范式,旨在通过将横切关注点(如日志记录、性能监控、事务管理等)从业务逻辑中分离出来,以提高代码的模块化和可维护性。我自己的理解就是,在不改变原始代码的前提下,追加代码的功能。

原始代码里的所有方法都称为“连接点”,所要追加新功能的方法称为“切入点”, 所追加的新功能称为“通知”,有了“通知”和“切入点”,就要进行两个之间的绑定,这个绑定称为“切面”,“通知”和“切入点”的绑定是多对多的关系,一个通知可以连接多个切入点,一个切入点也可以连接多个通知

2.引入Aop的坐标

<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

3.定义Aop的通知类

在该类的上方加上两个注解,@Component 把该类管理到容器中,@Aspect 说明该类是通知类

同时,spring的配置类上方还要加上@EnableAspectJAutoProxy注解,该注解可以说是用来扫描通知类的,与通知类的@Aspect注解相对应

4.定义切入点

假设在Dao接口中有几个方法,在接口的实现类中分别实现了这些方法,现在要为某个方法追加新的功能,但是又不能改变实现类中方法的代码,这就引入的Aop的作用

在所定义的Aop通知类里面定义切入点,目的是要明确哪些方法要追加新功能

4.1.定义对照切入点的方法

在通知类中定义一个方法,该方法无参数,也没有内容,该方法是要对应切入点,在方法的上方加上@Pointcut注解,表示这是连接切入点的方法,在注解的括号里,加上切入点的路径,”execution"表示执行,要执行该路径,在路径的前面有一个“void”,这表示切入点的类型,现在在通知类中就定义好了一个方法表示切入点。

4.2.切入点路径的表示

除了上述所定义的切入点的绝对路径以外,还有一种简单的方法,可以一次性定义多个切入点的路径。

使用 * 号和 ".." 两个点,* 号代表一个或多个, ".." 代表没有或多个

举个例子

把之前的绝对路径改变一下,把里面的一些类和包改成了 * 号,第一个 * 号表示切入点的类型,意思是可以是任意类型,第二个 * 号表示包,意思是可以是com.example.spring_aop这个包下面的任意包,第三个 * 号表示接口或者实现类,意思是任意的接口或者实现类下面的select()方法,当然,方法也可以用 * 号表示,意思是任意接口或者实现类下面的任意方法,而select()方法里面的参数用 .. 表示,意思是可以没有参数或者多个参数。

改成这种形式的路径之后,程序会根据所定义的路径,去匹配你的包,接口或者实现类,最后匹配方法,这种路径方式可以一次性的匹配到多个切入点,简化的开发过程,在实际开发中也是非常常用的方式

5.定义通知方法

通知方法有很多类型,最主要的有三个类型,分别是前置通知,后置通知,环绕通知,其中环绕通知是开发中最常用的,也是最重要的,环绕通知可以包含前置通知和后置通知

在通知类中定义一个通知方法,该方法的内部内容就是对切入点所追加的新功能

5.1.前置通知

在通知方法的上方加上@Before注解,注解后面加上之前定义的对照切入点的方法,该注解的意思是在执行切入点之前,先执行通知方法,这样就实现了把新功能加到了切入点的前面

5.2.后置通知

同理可得,后置通知是把追加的新功能放在切入点的后面执行

5.3.环绕通知

5.3.1.无返回值的环绕

环绕通知最大的特点就是需要调用原始方法,原始方法就是切入点,通知方法的括号里的参数是生成一个对象,在下面用proceed() 方法调用原始方法,所以,pjp.proceed() 就代表原始方法的执行,而所追加的新功能写在pjp.proceed() 的上方就是前置通知,写在下方就是后置通知

环绕通知还要抛出异常,因为在环绕通知方法里面调用了原始方法,不确定原始方法中是否存在异常,所要环绕通知要进行抛异常处理

5.3.2.有返回值的环绕

如果原始方法是一个有返回值的方法,则需要在通知方法里面把返回值进行返回,同时,通知方法的类型也要改成Object 类型

定义一个参数接收原始方法的返回值,然后在通知方法里再返回出去

6.获取切入点的信息

在环绕通知方法里面,用 pjp 对象,调用 getSignature() 方法,可以获得有关原始方法的一切信息,包括原始方法的类型,名字等等,把所有的信息封装到定义的对象 signature 里面,然后再通过该对象的具体方法取出对应的信息

如果原始方法含有参数,可以用 pjp.getArgs() 方法获得原始方法是参数,参数以数组类型获取

7.整体架构

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

托马斯家的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值