Spring IOC源码之getBean()
2021-06-19 14:27:54 37 举报
Spring Ioc创建Bean源码流程图
作者其他创作
大纲/内容
进行属性赋值
项目包位置:com.learn.springtest.circularDependencyTest
createBean( ... )
创建bean实例(策略)
如果不存在,则添加
早期对象InstB = InstB@2385
返回实例 instB
doGetBean( ... )
createBeanInstance( ... )
this.alreadyCreated.add(beanName)
调用自定义初始化方法(如果有)
afterSingletonCreation(beanName)
registerDisposableBeanIfNecessary( ... )
String[] dependsOn = mbd.getDependsOn()
applyBeanPostProcessorsBeforeInitialization( ... )
beforeSingletonCreation(beanName)
调用bean后置处理器的初始化前置方法
instantiateBean( ... )简单的包扫描形式
if (mbd.isSingleton())
invokeAwareMethods( ... )
工厂bean 处理
初始化Bean
addSingletonFactory( ... )
sharedInstance != null
return exposedObject
do干活的
放入三级缓存(singletonFactories)
getSingleton(beanName)
if (!typeCheckOnly) { markBeanAsCreated(beanName);}
public class MainClass { public static void main(String[] args) { new AnnotationConfigApplicationContext(MainConfig.class); }}@Configuration@ComponentScan(basePackages = {\"com.learn.springtest.circularDependencyTest\"})@ImportResource(locations = \"classpath:Beans.xml\")public class MainConfig { }public class InstanceA { private InstanceB instanceB; // 忽略 setter、getter}public class InstanceB { private InstanceA instanceA; // 忽略 setter、getter}
遍历 item
applyBeanPostProcessorsAfterInitialization( ... )
AbstractBeanFactory.getBean( ... )
获取bean定义
Object sharedInstance = getSingleton(beanName)
<bean id=\"instanceA\" class=\"com.learn.springtest.circularDependencyTest.InstanceA\" > <property name=\"instanceB\" ref=\"instanceB\"></property></bean><bean id=\"instanceB\" class=\"com.learn.springtest.circularDependencyTest.InstanceB\" > <property name=\"instanceA\" ref=\"instanceA\"></property></bean>
getBean( ... )
如果上述判断为 true,则说明当前beanName是正在创建中的多例对象抛异常,不进行后续处理
为什么以 @Bean的形式注入,无法解决循环依赖问题?修改后的配置类:@Configuration@ComponentScan(basePackages = {\"com.tuling.springtest.circularDependencyTest\"})// @ImportResource(locations = \"classpath:Beans.xml\")public class MainConfig { @Bean public InstanceA instanceA(InstanceB instanceB) { InstanceA instanceA = new InstanceA(); instanceA.setInstanceB(instanceB); return instanceA; } @Bean public InstanceB instanceB(InstanceA instanceA) { InstanceB instanceB = new InstanceB(); instanceB.setInstanceA(instanceA); return instanceB; }}答:首先,我们需要了解一个执行顺序: 创建早期对象(createBeanInstance) --> 放入三级缓冲(addSingletonFactory) --> 填充属性(populateBean) 这个需要说到属性赋值(解决循环依赖)的形式了,属性赋值形式是发生在 populateBean方法的时候,也就是说在此之前,已经将其早期对象放入了三级缓冲中了,那么依赖当前(早期)对象的bean对象在实例化时,在进行依赖属性赋值时,就可以直接从缓冲池中获取到其依赖的早期对象实例了。 回到问题,@Bean的形式之所以无法解决循环依赖,是因为设置其属性值(依赖对象)的发生点是 创建早期对象这一阶段,调用的是三大策略中的 工厂方法(@Bean注入)。究其根本,是没有来得及放入缓存。
String beanName = transformedBeanName(name)
invokeCustomInitMethod( ... )
配置文件:resources/Beans.xml
处理 FactoryBean类型的实例对象
早期对象InstA = InstA@2385
标记bean为已创建(或即将创建)
autowireConstructor( ... )@Autowired标注在构造方法上
多级缓存
singletonObjects (单例缓冲池)
属性赋值
getBean(dep)
isPrototypeCurrentlyInCreation(beanName)
initializeBean( ... )
earlySingletonObjects(早期对象缓冲池)
首先,判断是否存在循环依赖(抛异常)其次,注册两者依赖关系
doCreateBean( ... )
AbstractAutowireCapableBeanFactory.createBean( ... )
instantiateUsingFactoryMethod( ... )工厂方法(@Bean形式)
(InitializingBean) bean).afterPropertiesSet()
创建 InstanceA
真正干活的...
调用bean后置处理器的初始化后置方法
如果单例缓冲池(singletonObjects)中不存在,则 加入工厂缓冲池(singletonFactories)中,并且从早期对象缓存池(earlySingletonObjects)移除;如果存在,do nothing!!!
1、加入单例缓冲池(singletonObjects )2、移除另外两个缓存中的对象
invokeInitMethods( ... )
populateBean( ... )
初始化 bean实例
校验(是否抽象类)
初始化当前bean所依赖的bean
markBeanAsCreated(String beanName)
sharedInstance == null
singletonObject = singletonFactory.getObject()
this.singletonsCurrentlyInCreation.remove(beanName)
return singletonObject
创建 InstanceB
创建前
设置属性值时,发现需要实例化instB
同样设置属性值时,发现需要实例化 instA
是否允许暴露早期对象(解决循环依赖)
循环依赖项目演示:
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)
为什么 在构造器上标注了@Autowired,无法解决循环依赖问题?代码如下(不加载 Bean.xml):@Componentpublic class InstanceA { private InstanceB instanceB; @Autowired public InstanceA(InstanceB instanceB) { this.instanceB = instanceB; } // 忽略 setter、getter}// InstanceB 也是类似答:因为创建早期对象时,就需要解决依赖问题。说到底,还是执行顺序的问题(没有放入缓存中)当前情况下使用的是三大策略中的 autowireConstructor方法(@Autowired标注在构造器上)
如果是InitializingBean类型
解决循环依赖
返回早期对象
将bean注册为一次性的(单例)
别名解析(去除工厂前缀)
侧重分析生成bean的过程,所以后续流程是else逻辑
创建后
首先,尝试从单例缓冲池中(singletonObjects)获取,如果存在,直接返回;如果不存在,且创建中,则从尝试从早期对象缓存池(earlySingletonObjects)中获取,如果存在,直接返回;如果不存在,且早期引用允许被创建,则尝试从工厂缓冲池(singletonFactories)中获取工厂对象;如果工厂bean不为空,直接获取实例bean对象,然后放入早期对象缓冲池中,再删除工厂缓冲池中的元素,最后返回实例对象;如果工厂bean为空,返回null。
singletonFactories(单例工厂缓冲池)
this.singletonsCurrentlyInCreation.add(beanName)
问题2:
返回实例 instA
填充 bean实例对象属性值
问题1:
0 条评论
下一页