Spring核心思想之 AOP:AOP如何影响DI并引入三级缓存解决DI中涉及代理的问题
Spring中AOP的实现与在Spring核心思想之 AOP:在自定义容器基础上实现AOP功能中实现的自定义AOP一样,采用后置处理器方式。在Spring的核心思想之DI:详解Spring DI循环依赖实现机制文中末尾提到了一个问题,为什么是三级缓存而不是二级。
下面示例AOP是如何影响DI的?
AService和BService依赖注入,如果A没有后置处理器相关操作,AService和BService如上图就完成了bean生成。然而如果存在后置处理器呢?类似于下图:
BService注入AService后,系统就会自动提供一个名为 AsyncAnnotationBeanPostProcessor 的处理器,在这个处理器中会生成一个代理的 AService 对象,并用这个对象代替原本的 AService。关键在于:原本的 AService 和新生成的代理的 AService 是两个不同的对象,占两块不同的内存地址!
此时就产生了一个问题:BService中注入的AService与最终的AService不一致!!!下面就是Spring提供的三级缓存的方案:
创建一个 AService 的时候,通过反射刚把原始的 AService 创建出来之后,先去判断当前一级缓存中是否存在当前 Bean,如果不存在,则:
-
-
首先向三级缓存中添加一条记录,记录的 key 就是当前 Bean 的 beanName,value 则是一个 Lambda 表达式 ObjectFactory,通过执行这个 Lambda 可以给当前 AService 生成代理对象。
-
然后如果二级缓存中存在当前 AService Bean,则移除掉。
-
现在继续去给 AService 各个属性赋值,结果发现 AService 需要 BService,然后就去创建 BService,创建 BService 的时候,发现 BService 又需要用到 AService。于是就先去一级缓存中查找是否有 AService,如果有,就使用;如果没有,则去二级缓存中查找是否有 AService,如果有,就使用;如果没有,则去三级缓存中找出来那个 ObjectFactory,然后执行这里的 get("AService")方法。关键操作就在这个方法中:
在执行的过程中,会去判断是否需要生成一个代理对象,如果需要就生成代理对象返回,如果不需要生成代理对象,则将原始对象返回即可。最后,把拿到手的对象存入到AService二级缓存中以备下次使用,同时删除掉三级缓存中对应的数据。这样 BService 所依赖的AService 就创建好了(不管是原始的还是代理对象都在二级缓存中了)。
接下来继续去完善 AService,去执行各种后置的处理器,此时,有的后置处理器想给 AService 生成代理对象,发现 AService 已经是代理对象了,就不用生成了,直接用已有的代理对象去代替 AService 即可。
所以得出之前文章中的结论:三级缓存的使用将AOP提前操作了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?