当前 BeanDefinition不存在 父BeanDefinition
在红框位置去判断 当前bean有没有父bean, 如果没有, 则判断当前 BeanDefinition有没有实例化 RootBeanDefinition, 然后去生成一个新的 RootBeanDefinition, 不管有没有实例化都生成
父子BeanDefinition具体可以看标题三, 如下图所示
网络异常,图片无法展示|
最后会直接进入这个方法, 将当前 BeanDefinition放入 mergedBeanDefinitions 中
当前 BeanDefinition存在 父BeanDefinition
流程如下:
- 获取当前 BeanDefinition 的 父BeanDefinition名字
- 判断当前 beanName是否等于 parentBeanName
- 不相等:
- 递归 继续进行合并
- 相等:
- 获取 父BeanFactory
- 如果 父Bean工厂 实现了 ConfigurableBeanFactory 接口则 递归合并
- 若未实现则抛出异常
FactoryBean
这边会通过 beanName去判断当前 bean是不是一个 FactoryBean, 具体实现如下图所示
在 isFactoryBean(String name) 方法中, 第一行代码的降价在下面 FactoryBean标题下面
上图中, 我特意用红框圈出来一个方法, 这个方法的作用是: 通过 beanName去单例池中取数据, 但是这个时候是获取不到的, 因为我们还没有去生成 bean对象, 所以继续往下走
在下面代码中, 去做判断, 如果当前 beanName去取不到 BeanDefinition, 就去判断它的 父BeanDefinition有没有实现 FactoryBean
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) { return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name); } 复制代码
最后, 拿到合并之后的 BeanDefinition, 在往下走, 去判断 BeanDefinition的类型, 在判断是不是一个 FactoryBean, 在返回
获取FactoryBean对象
获取FactoryBean对象靠的是 getBean(String name)方法
我们可以看到, 这个方法的入参是在我们的 beanName前面增加了一个符号 &
我们进入这个方法内部去看一下
这里我们看到了熟悉的代码, 这行代码会根据你传入的 name不同而有所变化
String beanName = transformedBeanName(name); 复制代码
如上图所示, 可以看到, 我们在 实例化非懒加载单例Bean的时候, 有三个地方调用到了 getBean(String name)方法, 且第一次调用在 beanName前加了符号 &
在 getBean(String name)中, 会通过 transformedBeanName
方法去获取 beanName
然后根据获取到的 beanName去单例池中查找 获取单例对象, 如果获取到了单例对象, 那么会根据 bean的单例对象, beanName和传进来的 name去获取 bean实例
如果没有获取到了单例对象, 则会继续进行 bean的生命周期, 最后生成 bean的单例对象, 具体可以看我的下一篇Spring文章
创建 Bean对象
创建Bean对象就要用到 getBean(String beanName)方法了, 对于 getBean(String beanName) 方法的源码解析, 将作为下篇Spring系列文章发布在我的: Spring专栏
getBean 方法就是去创建一个Bean对象, 之前我还简单的手写模拟过整个过程, 感兴趣的可以去看一下Spring之手写模拟Spring Bean的创建
实现SmartInitializingSingleton接口
我们来实现这个接口, 会自动生成一个方法
通过上面的分析, 可以知道, 这个方法的执行时间是: 所有单例Bean都实例化之后
因为是在所有Bean实例化之后才去判断当前的Bean有没有实现这个接口
网络异常,图片无法展示|
三、合成BeanDefinition-父子BeanDefinition
生成父子 BeanDefinition代码如下
<bean id="juejin1" class="com.ningxuan.service.Juejin" scope="prototype"/> <bean id="juejin2" class="com.ningxuan.service.Juejin" parent="juejin1"/> 复制代码
因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。
而在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的BeanDefinition。