0
点赞
收藏
分享

微信扫一扫

【Spring源码】 FactoryBean接口

Gaaidou 2021-09-26 阅读 127

容器初始化阶段 实例化原始bean

启动容器的时候,如果当前bean 实现了FactoryBean,则先实例化将name改成(&original),beanName=original,将BD.isFactoryBean改为true,先实例化的也是原生bean,单例池存的就是
{original(beanName),@Original(原实例)},

先给name加个前缀 &

beanName会去除&,但是name还是&开头的

先实例化原始bean,beanName作为一级缓存的key

最后尝试替换成getObject,但是发现是&符号开头,且为FactoryBean类型,则不调用getObject方法,返回原始实例

如果手动调用getBean("&original"),和上面的流程是一样的,只不过可能是从缓存中先取出原始bean

getBean("original")

getObject的实例在启动阶段不会被实例化,必须得等到getBean("original")的时候再实例化,
SmartFactoryBean 如果实现的是这个接口,并且重写的isEagerInit()返回的是true,提前触发getObject

根据原始bean的beanName,先从缓存中取出原实例(原实例在容器初始化阶段就已实例化)

如果name 是 & 开头的,则返回原实例

是否是FactoryBean类型,不是的话直接返回

是的话往下走, 先FactoryBean的缓存factoryBeanObjectCache中拿getObject()返回的bean,拿不到调用原实例的getObject

调用原实例的getObject

最后加入把替换成getObject()返回实例 加入factoryBeanObjectCache缓存中

总结:

  1. 实现FactoryBean接口的bean会创建两个对象,一个是原始bean,一个是FactoryBean的getObject()返回的bean
  2. 原始bean在容器refresh的阶段就会创建,并且会放入一级缓存中,key为无&的名称,由于这个阶段在容器调用getBean的时候,会由于它是FactoryBean类型,给他的name加上&,所以实例化后的替换阶段会直接返回原实例,不会触发getObject
  3. 触发getObject一般不会在refresh阶段,需要你手动调用getBean("原始bean名称"),除非你实现SmartFactoryBean接口,并且重写isEagerInit()返回true
  4. 触发getObject()会返回一个新对象,并且有一个专门存放这种bean的缓存factoryBeanObjectCache,{原始bean名称 :getObject返回的实例}
举报

相关推荐

0 条评论