从getBean()的角度来看Bean的创建流程
通过上下文对象获取Bean实例所经过的方法调用链大致为下图所示。
这一节主要是依据这个调用链进行初步的流程解析
1.通过上下文对象获取Bean
ApplicationContext ac = new ClassPathXmlApplicationContext("methodOverride.xml");
FruitPlate fruitplate1 = (FruitPlate) ac.getBean("fruitplate1");
2.获取Bean
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
//调用过程的getBean()
//工厂类型为DefualtListBeanFactory
return getBeanFactory().getBean(name);
}
3.实际去获取bean
@Override
public Object getBean(String name) throws BeansException {
// 此方法是实际获取bean的方法,也是触发依赖注入的方法
return doGetBean(name, null, null, false);
}
4.解析doGetBean(),该方法进行了哪些操作
- 判断一级缓存中是否存在该Bean
- 解决循环依赖
- 父子容器不考虑(Spring中不进行考虑)
- 标记该BeanName正在创建中(加入集合的方式)
- 获取rootBeanDefinition,在这个过程中可以对不存在的BeanName进行校验
- 单例模式创建Bean
在准备创建Bean时有几点要注意
(1)在调用getSingleton()方法时,方法内会先去判断一级缓存中是否存在了该Bean
(2)如果一级缓存中没有就会通过以下匿名内部类的方式来调用createBean()
sharedInstance = getSingleton(beanName, () -> {
try {
// 为给定的合并后BeanDefinition(和参数)创建一个bean实例
return createBean(beanName, mbd, args);
}
5.解析createBean(beanName, mbd, args)
- 获取Class<?>
怎么获取一个类的类型呢?
其实不难理解,我们通过配置文件中class=“类的全限定名”,获得到一个 全限定类名 的字符串。然后在通过Class.forName( "String")反射得到一个类类型
- 调用doCreateBean(beanName, mbdToUse, args);
6.解析doCreateBean(beanName, mbdToUse, args)
- 根据执行bean使用对应的策略创建新的实例,如,工厂方法,构造函数主动注入、简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
最后附上一张方法调用图