专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Spring AOP 源码解析(二),创建代理对象、循环依赖的代理对象如何解决

创建代理对象

接着上一篇文章,在 shouldSkip 方法中已经将 Advice 通知方法生成了 Advisor 对象并且缓存好了

57_1.png

然后调用 getAdvicesAndAdvisorsForBean 方法去获取当前 Bean 的拦截器(也就是 Advice 通知),这个方法首先从缓存中获取到已经缓存好的 List<Advisor> ,然后挨个的检查对应的 Advisor,这个方法首通过反射获取当前类的所有的方法(包括父类)然后调用 matches 方法从 Advisor 中取出 Pointcut 表达式进行匹配检查,只要有一个方法满足条件么就返回为 ture 表示需要创建代理对象

57_2.png

57_3.png

然后回到 AbstractAutoProxyCreator 的 wrapIfNecessary 方法中,当 specificInterceptors 不为 null 的时候表明了需要创建代理,就会调用 createProxy 方法

57_4.png

这里又会调用 buildAdvisors 主要是对默认的一些拦截器做一些包装和检测

57_5.png

57_6.png

然后我们回到 AbstractAutoProxyCreator 的 createProxy 方法,在最后一步会调用 proxyFactory.getProxy(getProxyClassLoader()); 来创建代理对象

57_7.png

57_8.png

我们使用 AOP 的时候发现这里的 proxyTargetClass 始终返回为 true,它的这个值是来源于 AbstractAutoProxyCreator 的 createProxy 方法中的 proxyFactory.copyFrom(this); 这个方法,当前 this 对象是 AnnotationAwareAspectJAutoProxyCreator

57_9.png

随后判断如果我们的类如果是接口或者是一个 ProxyClass 的话就返回 JDK 动态代理对象,否则的是就返回 CGLIB 的动态代理对象

到此回到 AbstractAutowireCapableBeanFactory 的 doCreateBean 的 initializeBean 方法调用中返回了代理对象

57_10.png

然后我们返回到 AbstractFactory 的 doGetBean 方法,再看看这段逻辑

57_11.png他不是直接调用 createBean 的是先调用了 getSingleton 方法

57_12.png在这个方法中首先调用 singletonFactory.getObject 去调用 createBean 方法,然后检测到该对象是一个新的单例对象就调用 addSingleton 放入容器中

57_13.png到此创建一个完整的 Bean 实例完成了,那么最后就还有一个问题就是,由于需要去解决循环依赖问题,导致在调用初始化方法前其实就将 Bean 实例放入到了早期 Bean 实例中,可能会导致注入的都不是代理对象

处理循环依赖时候是如何解决代理对象问题的

比如 A 依赖 B,B 又依赖 A;同时我们又定义了 AOP 逻辑包含到了 A 和 B 的方法它们需要被代理,前文讲过首先我们通过反射创建 A 的早期实例然后放入到 singletonFactories 中,然后再调用 populateBean 进行依赖注入的时候发现了 A 依赖于 B,这个时候就要开始 B 的实例化,这个时候在 AbstractBeanFactory 的 doGetBean 的 getSingleton 方法就能起到作用它能从 singletonFactories 创建出 A 实例来,这个时候创建出来的就是这个 A 代理对象,我们来看下它是如何做到的

首先在创建 singletonFactories 的时候是放入的一个 ObjectFactory 的实现

57_14.png

57_15.png然后的调用 singletonFactories 中的 singleFactory.getObject 方法会调用到该方法 57_16.png遍历 BeanPostProcessor 最终会调用 AnnotationAwareAspectJAutoProxyCreator 的 getEarlyBeanReference 方法

57_17.png

熟悉的地方又来了回到了 wrapIfNecessary 上面讲过的方法中了。最后由于 A 调用初始化方法针对代理对象来操作即可,这样一个完整的 Bean 的实例创建就算完成了

文章永久链接:https://tech.souyunku.com/26038

未经允许不得转载:搜云库技术团队 » Spring AOP 源码解析(二),创建代理对象、循环依赖的代理对象如何解决

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们