Spring AOP = 责任链模式 + 代理模式

这里就不扯什么是AOP以及AspectJ的历史了,在一般大众的认知中,AOP就是在方法的前后做一些事情(Spring默认也就是方法级别的AOP)。接下来,让我们一步步实现AOP。

这是一个很普通的方法UserService#sayHello。

如何在sayHello前后做一些事情呢?最粗暴的做法是:

但这并不符合开闭原则,也不通用。如果需要在OrderService#order方法前后也做一些事情,就要把代码拷贝一份。

所以,我们必须将sayHello和sayHello前后要做的事情进行分离,而分离的目的是为了下次更好的相聚(组合)。

Spring AOP的做法是,抽象出以下概念:

  • Pointcut
  • Advice
  • Advisor

Pointcut俗称切点,可以简单理解为"怎么切/切哪里",也就是一个匹配规则,比如我们常见的AspectJExpressionPointcut,允许我们配置切点表达式:

execution(* com.bravo.test.service.UserService.sayHello(..))

Advice则是具体的增强逻辑,即前面说的"方法前后要做的事情"。

而Advisor=Pointcut+Advice。

对于符合Pointcut规则的目标方法应用Advice,在目标方法前后做一些事情。

尽管在我看来这些概念已经很清晰,但对于初学者来说还是有点绕。所以,这里再做一步简化,只留下Advice的概念,丢弃Pointcut和Advisor。没有Pointcut怎么知道哪些方法需要增强呢?交给调用者手动组装。比如:

当然,Spring内部有一个匹配过程,代码大致如下(这里不是Spring的源码):

Advisor持有Pointcut,方法匹配成功,则返回advice用于增强

讲到这,对于如何实现AOP应该有一个模糊的概念了。

接下来我们讨论最难的两个问题:

  • 如何把advice嵌入目标方法前后
  • 如何链式执行advice

在这里,Spring又抽象出了一个新的概念:MethodInvocation。

这是啥?Spring很清楚,所谓AOP,就是在调用目标方法前后额外执行一些内容。Java的反射已经封装好Method这个类,所以整个过程就是:

那我能不能把这个过程也封装一下呢?我把"Method执行前后需要额外做一些操作"这个过程抽象成MethodInvocation(方法执行)。

里面只定义一个方法proceed,表示执行方法,而且执行的时候要自动把advice也执行掉。

然后,配套的还有MethodInterceptor:

这又是啥?通俗讲就是方法拦截器,在执行方法前做些事情。在Spring中MethodInterceptor继承自Advice,大家直接看成Advice即可。

所以,现在变成了这样:

把经过Interceptor执行Method的这个过程封装成MethodInvocation

接着,我们使用JDK动态代理为userService生成代理对象。代理对象会将一次方法调用委托到目标对象,但在此之前会执行advice:

那么,如何产生链式调用呢?

MethodInvocation就是Filter模式中的FilterChain,持有Interceptor并且负责推进下一个Interceptor

具体代码放在gitee了:

gitee.com/bravo1988/d...

相关推荐
不务专业的程序员--阿飞6 分钟前
【SQL 如何解锁递归】
java·数据库·sql
嘵奇13 分钟前
Spring Boot拦截器详解:原理、实现与应用场景
java·spring boot·后端
八股文领域大手子13 分钟前
Java死锁排查:线上救火实战指南
java·开发语言·面试
jackson凌20 分钟前
【Java学习笔记】finalize方法
java·笔记·学习
fanTuanye23 分钟前
redis 缓存穿透,缓存击穿,缓存雪崩
java·redis·缓存
神秘的t40 分钟前
Spring Web MVC————入门(2)
java·spring·mvc
开开心心就好1 小时前
高效全能PDF工具,支持OCR识别
java·前端·python·pdf·ocr·maven·jetty
冷心笑看丽美人1 小时前
Spring MVC数据绑定和响应 你了解多少?
java·spring·mvc
XQ丶YTY1 小时前
大二java第一面小厂(挂)
java·开发语言·笔记·学习·面试
一零贰肆1 小时前
深入理解SpringBoot中的SpringCache缓存技术
java·springboot·springcache·缓存技术