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