背景
前面我们知道,被 @RefreshScope 注解的实例,在扫描生成 BeanDefiniton 时,被偷龙转凤了:注册了两个 Bean 定义,一个 beanName 同名、类型是 LockedScopedProxyFactoryBean.class 代理工厂 Bean,一个 scopedTarget.beanName 的目标 Bean。
当程序使用 getBean 获取一个被 @RefreshScope 注解的实例时,容器返回的是一个JdkDynamicAopProxy 代理对象, 它是怎么从 ScopedProxyFactoryBean 创建的呢?本文记录这个过程的跟踪流程。
代理类的创建
首先,从 spring 的抽象 Bean 工厂类 AbstractApplicationContext 开始,当 getBean(type) 调用时,开启 Bean 工厂生产的流程:

接着,它背后是 DefaultListableFactoryBean,开始干活,resolveBean 返回需要的 Bean 实例:

继续跟resolveNamedBean,定位到背后的 Bean Definition :

注意,这里在查找候选类型的时候,由于扫描时注入了两个相同类型的 Bean

注意这里,还记得吗,代理类和委托类类型相同,candidateNames 返回了两个名称 beanName 和 scopedTarget.beanName,但是真正委托类的属性被修改了,这里只会得到一个名称:

一路委托调用:


终于到了真正干活的地方 doGetBean:

- 先查找 beanName 所在的单例对象,实际就是
ScopedProxyFactoryBean对象; - 接着调用
getObjectForBeanInstance创建实例。
核心代码到了,DefaultSingletonBeanRegistry.getSingleton,它开始查找 beanName 所在的单例工厂:

接着回到 AbstractBeanFactory.getObjectForBeanInstance 开始从单例工厂创建实例:

因为前一步取到的是 ScopedProxyFactoryBean 的实例是一个 FactoryBean,所以直接进入最后一个分支:

doGetObjectFromFactoryBean 调用 ScopedProxyFactoryBean.getObject:

所以这个调用链,最终返回了 ScopedProxyFactoryBean 在被注入 BeanFactory 时创建的那个 proxy 代理类:

启示录
当程序使用 getBean 获取一个被 @RefreshScope 注解的实例时,最终得到的是 LockedScopedProxyFactoryBean 的 getObject() 返回值,它是一个 JdkDynamicAopProxy 代理对象。
中间对 ScopedProxyFactoryBean 初始化的流程,含有很多细节,比如 GenericScope 注册的 BeanDefinitionRegistryPostProcessor 对代理 Bean 定义添加了一个构造函数的参数,它是怎么在 LockedScopedProxyFactoryBean 初始化时使用的。
还有 AbstractAutowiredCapableBeanFactory 的织入回调 invokeAwareMethod ,BeanDefinitionRegistryPostProcessor 回调等,水不知几深,浅尝辄止尔!
参考
看到一篇很完整的文章,可以参考补充:《SpringCloud @RefreshScope动态刷新配置原理浅析》



















