文章目录
- 一、getBean()
- 二、第一次调用getSingleton()
- 三、第二次调用getSingleton()
- 四、createBean()
- 五、doCreateBean()
- 六、createBeanInstance()
- 七、autowireConstructor()
- 八、populateBean()
- 九、initializeBean()
- 十. invokeInitMethods()
- 十一、小结
https://blog.csdn.net/zxd1435513775/article/details/120935494?spm=1001.2014.3001.5501
Spring源码系列(四)——ConfigurationClassPostProcessor功能解析
https://blog.csdn.net/zxd1435513775/article/details/121113933?spm=1001.2014.3001.5501
Spring源码系列(六)——容器的刷新(下)
在第四篇和第六篇中,都分析到了一个方法,就是getBean()
,这行代码的意思是:从容器中获取Bean
,如果没有,则去创建Bean
。所以在查看Spring
源码时,只要看到这个方法,就要知道是去实例化Bean
了。
这个方法的具体实现位于AbstractBeanFactory
类中,下面就来分析吧。
下面来看一下这个方法的详细代码:
// 根据name去获取对应的Bean实例
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected T doGetBean(
String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly){
/**
* 下面这个方法是通过 name 去获取 beanName,这里为什么不使用 name 直接作为 beanName呢?
* 有两个原因:
* 1、name 的值可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean 实现类所创建的 bean。
* 在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储方式是一致的,即 ,而 beanName 中是没有 & 这个字符的。
* 所以需要将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。
* 2、还是别名的问题,转换需要 &beanName
*/
String beanName = transformedBeanName(name);
Object bean;
/**
* 下面这个getSingleton()方法,在上面getBean()的时候也会调用,在Bean初始化的时候会调用
* 为什么需要这么做呢?
* 也就是说Spring容器在Bean初始化的时候先获取这个Bean对象,判断这个对象是否被实例化好了,
* 是不是已经被创建了。普通情况下绝对为空,但有一种情况可能不为空
* 从Spring容器中获取一个Bean,由于Spring中Bean容器是用一个map(singletonObjects)来存储的
* 所以可以理解getSingleton(beanName)等于beanMap.get(beanName)
* 由于getBean()方法会在Spring环境初始化的时候(就是对象被创建的时候调用一次)调用一次
* 还会在Bean初始化的时候再调用一次
* 此处为getSingleton()第一次调用,意思是去缓存里查询该beanName有没有被创建
*/
Object sharedInstance = getSingleton(beanName); // 此方法详解,看下面第二部分
// 此处拿到sharedInstance,不为空,表示已经实例化了,但属性有没有填充不确定
// 在分析FactoryBean的时候,分析了getObjectForBeanInstance()方法,下面我们就分析else的情况
if (sharedInstance != null && args == null) {
/**
* 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。
* 但如果 sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的
* bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回即可。
* 毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 判断是否是原型Bean,如果是原型,不应该在Spring容器初始化的时候创建
// 为什么要直接抛异常呢?因为在refresh()方法中的finishBeanFactoryInitialization()方法中
// 已经对bean进行了判断,BeanDefinition不是抽象的,不是懒加载的,是单列的才会进入执行到此处
// 所以会抛异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查Spring工厂中是否存在bean定义
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// 此参数为方法传入进来
if (!typeCheckOnly) {
// 添加到alreadyCreated set集合当中,表示他已经创建过一次
markBeanAsCreated(beanName);
}
try {
// 如果给的bean的定义是有父类的,则通过与父bean合并,返回给定顶级bean的RootBeanDefinition。
// 在使用xml配置Bean时,有个属性parent属性来指定父类
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 再次检查,检查合并后的bean是不是抽象的
checkMergedBeanDefinition(mbd, beanName, args);
// 获取所依赖的bean,保证对当前bean所依赖的bean进行实例化。
// 此处的意思是,被依赖的Bean要先进行实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 抛异常代码略
}
registerDependentBean(dep, beanName);
try {
// 又一次调用getBean()方法,此处获取的依赖bean,递归调用,获取即创建
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
// 抛异常代码略
}
}
}
// 此处才开始创建Bean,也是此处进行了getSingleton()方法的第二次调用
if (mbd.isSingleton()) {
// 此处为getSingleton()第二次调用,两处调用,形参不一样
// 先执行getSingleton()方法,在该方法中,可以调用lamda表达式
sharedInstance = getSingleton(beanName, () -> {
try {
// 此方法看下面第四部分
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
// 抛异常代码略
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
// 抛异常代码略
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
// 抛异常代码略
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
// 抛异常代码略
}
return convertedBean;
} catch (TypeMismatchException ex) {
// 抛异常代码略
}
}
return (T) bean;
}
二、第一次调用getSingleton()
下面来看下这个方法详细代码:DefaultSingletonBeanRegistry
类中
// 第一处getSingleton()是调用这个方法,根据beanName去singletonObjects中查询是否已经被实例化
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从singletonObjects中获取bean,如果不为空直接返回,不再进行实例化工作
Object singletonObject = this.singletonObjects.get(beanName);
// isSingletonCurrentlyInCreation()方法判断当前beanName是不是正在创建中
// 如果为null并且正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 去earlySingletonObjects中拿,注意这行集合里面存放的对象还没有被填充属性
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果也没拿到,说明还没有创建完成
if (singletonObject == null && allowEarlyReference) {
// 去存放Bean工厂的集合里拿,看看是不是Bean工厂
ObjectFactory singletonFactory =
this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
// 此集合是为了解决循环引用问题
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
// 正在创建的Bean会被放到这个singletonsCurrentlyInCreation集合中
return this.singletonsCurrentlyInCreation.contains(beanName);
}
这里要特别说一下singletonObjects
,earlySingletonObjects
,singletonsCurrentlyInCreation
,singletonFactories
四个作用,很关键!!!
singletonObjects
是个Map
,用于存放完全初始化好的Bean
,从这个Map
中取出的Bean
可以直接使用earlySingletonObjects
是个Map
,用于存放原始的Bean
对象,用于解决Bean
的循环依赖问题,注意:存到里面的对象还没有被填充属性,即还没有完成初始化!!!singletonsCurrentlyInCreation
是个Set
,用于存放正在创建中的Bean
singletonFactories
是个Map
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?