目录
3.getSingleton(String beanName, ObjectFactory singletonFactory)方法
4.createBean(beanName, mbd, args)方法
5. addSingletonFactory(beanName, singletonFactory) 方法
6.addSingleton(beanName, singletonObject)方法
一、前言
循环引用,简单来说是指A类中依赖B类,B类中又依赖A类,当然这个引用的链也可能更长(A->B->C->....->A);
Spring中对于单例模式的循环引用主要是两种,一种是构造函数的循环引用,一种是set注入的循环引用
构造函数的循环引用无法解决(后边会讲原因),这里主要讲set注入的循环引用,假设目前我们的引用链是A类依赖B类,B类也依赖A类(A->B->A)
二、源码分析
当spring解析注解或配置文件之后,所有的类将会以BeanDefinition的形式保存在容器中,然后对这些BeanDefinition实例化。
实例化用到的方法主要是AbstractBeanFactory. getBean(String name);
1.getBean(String name)方法
调用链
AbstractBeanFactory.getBean(String name);
->AbstractBeanFactory. doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly)
代码如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//传入的name可能是alias,也可能有&前缀(工厂类) 得转化一下
final String beanName = transformedBeanName(name);
Object bean;
//首先从缓存中获取 这里讲的缓存主要是
//singletonObjects, earlySingletonObjects 重点
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
....//省略部分代码
//如果缓存中存在 因为可能得到的事FactoryBean
//而我们需要的是FactoryBean.getObject创建的对象 在此作处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//如果缓存中没有
......//省略部分代码
try {
//我们的类可能继承了父类 将父类的属性合并一下
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//xml配置文件中使用了depend-on属性或者java文件中使用了@DependsOn 依赖的类先实例化
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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//如果这个BeanDefinition是单例
if (mbd.isSingleton()) {
//创建对象 主要是通过ObjectFactory创建
//注意:这里使用lambda表达式 创建了一个匿名内部类工厂
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
//如果缓存中存在 因为可能得到的事FactoryBean
//而我们需要的事FactoryBean.getObject创建的对象 在此作处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
......//省略部分代码
}
....//省略部分代码
return (T) bean;
}
2.getSingleton(beanName)方法
首先先看看getSingleton(beanName)从缓存中获取做了些啥。
调用链
DefaultSingletonBeanRegistry.getSingleton(String beanName)
//return getSingleton(beanName, true); //allowEarlyReference是true
->DefaultSingletonBeanRegistry.getSingleton(String beanName, boolean allowEarlyReference)
代码如下:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从singletonObjects中获取 这是一个Map<String, Object>
Object singletonObject = this.singletonObjects.get(beanName);
//singletonsCurrentlyInCreation是一个Set<String> 实例化之后会BeanName加入到集合里
//判断singletonsCurrentlyInCreation是否包含beanName,如果包含beanName 表示该beanDefinition已经实例化 但是
//还没有给属性赋值 (后边会提及)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从 Map<String, Object> earlySingletonObjects获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//如果earlySingletonObjects中没有 则获取ObjectFactory得到对象的引用
//至于ObjectFactory什么时候放入singletonFactories中 后边会提及
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//earlySingletonObjects 和 生成这个对象的ObjectFactory是互斥的
//通过ObjecFactory生成后 就放到earlySingleObjects中,以后无需
//ObjectFactory再创建了
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
对于之前没有实例化过得beanDefinition,这里肯定返回null,如果缓存中没有,那我们需要自己实例化对象。
3.getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法
接下来我们看DefaultSingleBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory)
如下:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
......//省略部分代码
//将beanName加入到singletonsCurrentlyInCreation中
beforeSingletonCreation(beanName);
......//省略部分代码
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
....
}
catch (BeanCreationException ex) {
....
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
这里主要是将beanName加入到singletonsCurrentlyInCreation集合中(前面从缓存中取对象时用到过),然后调用ObjectFactory.getObject方法 而通过doGetBean方法里匿名内部类可知,就是调用createBean(beanName, mbd, args)方法。
4.createBean(beanName, mbd, args)方法
代码如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
......//省略部分代码
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
...
}
catch (Throwable ex) {
...
}
调用链:
->doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
//实例化对象的关键
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//调用构造函数实例化对象
//到此对象已经被实例化了,只是依赖的属性还没有被赋值或实例化
//比如 A类中有个属性B,需要进行注入 此时B是没有注入的
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
......//省略部分代码
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//如果是单例&&允许循环依赖&&对象正在构建中(已经实例化,但是属性没有赋值)
//isSingletonCurrentlyInCreation就是判断singletonsCurrentlyInCreation
//中有没有beanName,在前面我们已经将beanName加入到该集合中了
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//将beanName和ObjectFactory放入SingleFactories中
//ObjectFactory 返回的事这里对象的引用(已经实例化,但是它的属性还没有赋值)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//给对象的属性赋值
populateBean(beanName, mbd, instanceWrapper);
//调用诸如init-method等初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
...
}
......//省略部分代码
return exposedObject;
}
5. addSingletonFactory(beanName, singletonFactory) 方法
这里我们注重看addSingletonFactory方法
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
初次实例化singletonObjects肯定不包含该beanName,这里我们将bean,ObjectFactory加入到了singleFactories,以便下次实例化时从缓存获取的时候 就可以通过这个ObjectFactory得到对象的引用了(虽然只是实例化了,属性还没有赋值,但当后边的 populateBean(beanName, mbd, instanceWrapper);执行完之后,属性就赋值完成了)
6.addSingleton(beanName, singletonObject)方法
最后我们再看一下Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法中的addSingleton(beanName, singletonObject);
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
当对象实例化流程走完之后,将beanName,singleObject放入singletonObjects中,以便其他对象依赖时从缓存中获取的时候进行返回
三、总结
spring中解决循环依赖 假设A类依赖B类,B类依赖A类(A->B->A)
那么当A实例化时会从缓存中获取
首先从singleObjects中获取,singleObjcts存放的对象是已经实例化,并且属性也赋值了
如果singleObjects中没有 则从earlySingletonObjects中获取,earlySingleObjects存放的是对象已经实例化,但是属性还没有赋值
如果earlySingleObjects中没有 则使用ObjectFactory获取对象的引用,放入earlySingleObjects中
当然如果A是第一次实例化,从缓存中返回null
这时需要我们自己实例化,首先调用构造函数实例化,然后在属性赋值前将beanName,和返回对象引用的ObjectFactory加入到singleFactories中(这也是构造函数依赖不能解决的原因,因为ObjectFactory加入到singleFactories中是在构造函数实例化之后)
最后进行属性赋值,
因为A依赖B,我们需要实例化B,对B做同样的处理,当B又依赖A时因为我们已经将获取A引用的ObjectFactory放入了singleFactories中,所以这里我们能获取到A的引用
最终将B的beanName,singleObject加入到缓存singleObjects中,向上递归,将A的beanName,siingleObject加入到singleObjects中。
附图: