zl程序教程

您现在的位置是:首页 >  后端

当前栏目

灵魂画手:图解 Spring AOP 实现原理

Spring图解AOP原理 实现 灵魂
2023-09-11 14:16:32 时间

本篇旨在让读者对 Spring AOP 实现原理有一个宏观上的认识,因此会丢失一些细节,阅读本篇文章前,希望读者对 Spring Ioc 以及 Spring AOP 的使用(@Aspect)由一定了解,话不多说,直接上图

准备工作

  • Service 类: 有 find 方法跟 save 方法,find 方法前后需要缓存操作,save 方法前后需要事务操作

  • CacheableAspect 切面类: 用于在 Service 的 find 方法前后进行缓存操作

  • TransctionlAspect 切面类: 用于在 Service 的 save 方法进行事务操作

  • LogAspect 切面类: 记录所有 Controller 的请求日志

Spring AOP 自动代理时机

在 service bean 的创建过程中(也就是getBean("service")),AOP 通过BeanPostProcess后置处理器操作进行介入 分为 2 种情况:

  • 用户自定义了targetSource,则 bean 的创建(实例化、填充、初始化)均由用户负责,Spring Ioc 不会在管该代理目标对象 traget,这种情况基本上不会发生,很多人用了几年 Spring 可能都不知道有它的存在

  • 正常情况下都是 Spring Ioc 完成代理对象 target 的实例化、填充、初始化。然后在初始化后置处理器中进行介入,对 bean 也就是 service 进行代理

创建代理操作 wrapIfNecessary

所有的重点都在wrapIfNecessary做了什么操作

代理的方法调用

创建完代理,代理如果调用方法呢?我们以 Jdk 动态代理为例子,方法的调用将会触发 invoke 方法。

Spring AOP 拦截器的执行顺序

从上面可以看出,Spring AOP 的代理 invoke 方法,其实是拦截器的执行。

我们先了解一下 Spring AOP 的执行顺序,跟栈很像,后进先出

AOP 拦截器执行原理

那么这个拦截器链又如何保证 before 在 after 之前呢?而且还能保证 find 方法的执行顺序?

这部分实现原理通过几句话是解释不完的,只能给出图大家了解个大概

具体拦截器源码:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 先调用before方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 继续链式调用
return mi.proceed();
}
}

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 先进行链式调用
Object retVal = mi.proceed();
// 再调用afterReturning方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}

压轴题:Spring AOP 遇上循环依赖

该部分难度系数十颗星,算是 Spring 源码最复杂的一块,这块弄懂可以说对 Spring 的理解已经达到阿里水准了。这里三言两语是不可能解释清楚的,只能贴个图,大家有个宏观上的认知。

总结

Spring AOP 是 Spring 重要的组成部分之一,本篇只是给读者宏观上的一个认识,具体还是需要阅读源码。

如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,

咱们下期见!答案获取方式:已赞 已评 已关~

学习更多JAVA知识与技巧,关注与私信博主(03)