这篇来记录bean的创建以及初始化等过程。从下面getBean()
方法开始,开头申明,自己推敲且水平有限,无关注释或者有说错的地方轻喷。
BeanFactory factory = new BeanFactory(new ClassPathResource("beans.xml"));
YourBean bean = factory.getBean(YourBean.class);
跟进getBean()
方法发现进入了AbstractBeanFactory.doGetBean()
中,方法申明如下,该方法中完成了bean的创建,依赖注入,赋值以及初始化等等..
doGetBean(final String name, @Nullable final Class requiredType, @Nullable final Object[] args, boolean typeCheckOnly)
大概的步骤如下
- 根据名称解析真实的
beanName
,比如将FactoryBean(&xxxx)
,alias
等特殊的bean转化成正式的beanName.
/**
* 会将BeanDefinitionMap传递过来的alias,factoryBeanName(&FactoryBeanName)转化成实际的beanName
*/
final String beanName = transformedBeanName(name);
- 尝试从缓存中获取单实例bean,获取到则直接返回实例对象
/**
* 尝试从缓存中获取单例对象定义信息
*/
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
....省略了一些异常信息
/**
* 处理FactoryBean返回的bean要是其中getObject()方法返回的对象
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
- 若默认层次的容器存在父容器,且该容器的
BeanDefinition
中没有该bean的定义信息那么会递归从父容器中获取bean
/**
* 判断该bean是否是多实例且正在创建,是则抛出异常
*/
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//获取父IOC容器对象
BeanFactory parentBeanFactory = getParentBeanFactory();
//父工厂对象不为null,且当前容器工厂中没有该beanName对应的BeanDefinition,则该bean会在父容器中创建
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 if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
- 在正常初始化之前下先初始化依赖的bean实例,也就是
dependsOn
标记的
//将GenericBeanDefinition合并为RootBeanDefinition,因为后面的操作频繁使用到RootBeanDefinition的属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//获取到所有的依赖beanName
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {//校验是否循环依赖
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName); //注册依赖bean
try {
getBean(dep); //实例化依赖bean
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
- 正式初始化单实例bean
// 正式实例化bean
if (mbd.isSingleton()) {
//通过创建Bean得到的ObjectFactory来获取单实例bean
sharedInstance = getSingleton(beanName, () -> {
try {
//这里为创建bean的核心方法 -> 将返回ObjectFactory供 getSingleton()方法获取单实例bean
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// ...省略了异常处理
}
});
//对FactoryBean的特殊处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
- 初始化多实例bean
//实例化多实例bean
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//前置处理,给prototypesCurrentlyInCreation中设置值,方便其他依赖bean检测是否正在实例化
beforePrototypeCreation(beanName);
//创建多实例bean
prototypeInstance = createBean(beanName, mbd, args);
} finally {
//后置处理,给prototypesCurrentlyInCreation移除对应的值
afterPrototypeCreation(beanName);
}
//对FactoryBean的特殊处理
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
- 初始化其他
Scope
的bean,和单实例多实例大同小异,就是通过BeanDefinition
判断scope的方式
//其他作用范围的bean的实例化方式
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
- 若需要做类型转化,则最后完成类型转化。其中requiredType可以在getBean()中申明需要返回的bean的类型
//查看是否需要类型转化,需要的话使用convert进行转化然后返回bean
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
} catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
大方向的步骤在上面已经全部展示,其中有几个很重要的点
- 一开始的缓存处理
-
FactoryBean
的特殊处理 - 获取正式的单例对象bean的
sharedInstance = getSingleton(beanName, objectFactory)
方法的细节 - 获取
ObjectFactory
的细节 - 处理循环依赖
缓存处理
- 因为Spring中的Bean默认是单例的,所以Spring在源码阶段为了追求性能,大量使用ConcurrentMap来做本地缓存处理,废话不多说直接进入上述源码。从
AbstractBeanFactory.doGetBean()
方法中跳转到该缓存处理逻辑,Spring使用了三级缓存来帮助我们初始化bean,并且用此来解决循环依赖的问题
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//尝试从已经初始化好的单例对象Map中(SingletonObjects)获取
Object singletonObject = this.singletonObjects.get(beanName);
//isSingletonCurrentlyInCreation:判断是否是正在创建的bean
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
////如果是正在被实例化的bean则直接返回
singletonObject = this.earlySingletonObjects.get(beanName);
//如果没有正在被实例化且允许提早引用,那么尝试在singletonFactories中获取ObjectFactory实例,从而可以解决循环依赖的问题
if (singletonObject == null && allowEarlyReference) {
//尝试获取单例工厂,其中singletonFactories储存着需要提前初始化的所有的ObjectFactory
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//使用单例工厂获取单例对象,同时设置到early单例缓存中
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
其中有几个需要特殊注意的属性
singletonObjects
: 指的是已经完成创建的单实例bean,其申明为
/**
* k-> beanName v-> bean instance
*/
private final Map singletonObjects = new ConcurrentHashMap<>(256);
singletonFactories
: 缓存了创建bean的ObjectFactory对象,用来解决循环依赖,创建时机是在循环依赖bean的赋值之前,即population()
/**
* k-> beanName v-> bean ObjectFactory 实例工厂
*/
private final Map> singletonFactories = new HashMap<>(16);
earlySingletonObjects
: 当bean还在创建的时候会暴露出引用地址,用来判断是否循环依赖,在从singletonFactory
缓存中获取到了依赖bean之后,会将bean添加进去。简化之后再次依赖的操作
/**
* k-> beanName v-> bean instance (bean未创建完毕也能通过getBean()获取到,用来检测循环引用)
*/
private final Map earlySingletonObjects = new HashMap<>(16);
- 缓存处理的主要三个步骤
//1.尝试从已经完全初始化好的单例缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
//2.若是正在创建的bean,且单例缓存中没有,那么则去二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
//3.二级缓存中没有获取到,从三级缓存中获取,若没有获取到则返回null
ObjectFactory> singletonFactory = this.singletonFactor,ies.get(beanName);
FactoryBean的特殊处理,无论我们是实例化单例对象还是从缓存中获取对象,后面都需要对获取的Bean进行二次检测看是否是FactoryBean,实现方法在AbstractBeanFactory.getObjectForBeanInstance()
方法中,主要方法源码如下
//
//判断是否是FactoryBean(是否以“&”开头)
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
//不是FactoryBean类型则抛出异常
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
.....省略一些缓存操作
//使用FactoryBean.getObject方法来获取真正的bean对象,不然可能获取的factoryBean对象而不是factory-method返回的bean对象
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
然后后面主要就是通过FactoryBean
的 getObject()
方法来返回真正的bean对象,否则可能返回的是名字为&factoryBeanName
的bean
获取正式的单例对象bean的sharedInstance = getSingleton(beanName, objectFactory)方法的细节,主要源码如下
//通过创建Bean得到的ObjectFactory来获取单实例bean
sharedInstance = getSingleton(beanName, () -> {
try {
//创建bean
return createBean(beanName, mbd, args);
});
其中getSingleton就是通过第二个参数传递的函数来充当声明ObjectFactory,然后通过getObject
方法实例化
这里的核心要观察createBean
方法
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
//给后置处理器一个机会返回代理对象,这里会回调`InstantiationAwareBeanPostProcessor`的方法来返回代理对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//创建bean的主要逻辑
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
//获取BeanInstance
instanceWrapper = createBeanInstance(beanName, mbd, args);
// 提早(在对属性进行赋值和初始化之前,即属性注入之前)的缓存单实例bean方便解决循环引用问题
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//将其的引用封装到ObjectFactory中并且添加到SingletonFactory中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//进行属性赋值
populateBean(beanName, mbd, instanceWrapper);
//初始化bean并返回初始化后的bean对象
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
创建bean的核心就四大步,详细过程如图
-
createBeanInstance
创建bean实例,底层通过判断构造方法,以及在getBean
方法传递的参数值、BeanDefinition
中申明的构造参数值来反射出实例对象 -
addSingletonFactory
在给属性值赋值之前将创建好的bean添加到三级缓存中,即singletonFactories
中,解决循环依赖 - 赋值
populateBean
给bean的属性填充值,若有依赖其他bean,则会递归初始化属性bean -
initializeBean
: 回调bean的初始化方法(init-method) ,afterProperties
等等..
解决循环依赖问题
当BeanA
中有属性B
,BeanB
中又有属性A
,则在初始化的时候就出出现循环依赖问题,如下图所示
那么Spring是怎么解决循环依赖问题呢?Spring 对使用setter/field注入的循环依赖提供解决方法,而通过构造方法的无法解决,因为在Spring创建bean的时候会使用构造方法创建bean,而此时还没有创建完成bean对象,无法进行提前缓存处理。
那么在源码中两依赖bean的执行流程如下:
- 创建
A
的时候,在populateBean
给属性初始化的时候会开始创建B
,并且在populateBean
方法之前会调用addSingletonFactory
方法将自己的bean提交暴露在三级缓存中 - 创建
B
的时候,在populateBean
给属性初始化的时候会开始创建A
,发现SingleObjects
容器中并没有A
,则继续创建A
- 创建
A
的时候,调用getSingleton
从缓存中查询的时候,由于第一次已经提前将A
缓存好了,那么将直接获取A
的引用,从而创建B
成功 -
A
发现B
成功,则也完成创建,又由于容器中bean是单例的,所有此时就完美的完成了循环依赖