Spring如何解决循环依赖

Spring如何解决循环依赖

先建立循环依赖的demo代码
dao中引用了service,service引用了dao。

Dao代码

@Component
public class MyDao  {

	@Autowired
	MyService service;

	public MyService getService() {
		return service;
	}

	public void setService(MyService service) {
		this.service = service;
	}
}

Service代码

@Service
public class MyService {

	@Autowired
	MyDao dao;

	public MyDao getDao() {
		return dao;
	}

	public void setDao(MyDao dao) {
		this.dao = dao;
	}
}

创建bean的流程在上一篇文章的流程图已经写得很清楚了,所以这里只写一些关键的步骤。

设置条件断点
在这里插入图片描述

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		// 从一级缓存即单例对象缓冲中获取bean
		Object singletonObject = this.singletonObjects.get(beanName);
		//一级缓存中的bean 为空,且当前bean正在创建
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //从二级缓存获取
			singletonObject = this.earlySingletonObjects.get(beanName);
			//二级缓存为空,并且允许提前曝光
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							//从三级缓存singletonFactories 中获取对应的ObjectFactory
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							//如果在三级缓存中存在,则放进二级缓存中,从三级缓存中remove掉
							if (singletonFactory != null) {
								singletonObject = singletonFactory.getObject();
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

因为第一次进来,拿到的sharedInstance为null。所以走到createBean注意这里的beanName是myDao

sharedInstance = getSingleton(beanName, () -> {
							return createBean(beanName, mbd, args);
						}

接下来调用AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#createBeanInstance(beanName, mbd, args),
myDao被放到了singletonFactories。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

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);
			}
		}

AbstractBeanFactory#getSingleton(String beanName, ObjectFactory<?> singletonFactory)完成对象的实例化之后,myDao被加入到了singletonsCurrentlyInCreation中,myDao就实例化完毕了。
在这里插入图片描述

接下来来到了属性的填充
AbstractAutowireCapableBeanFactory#populateBean(beanName, mbd, instanceWrapper);,beanName是myDao。
执行后置处理器,处理@Autowire注解,给myDao填充myService,AbstractAutowireCapableBeanFactory#ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

来到postProcessProperties里面的代码metadata.inject(bean, beanName, pvs);进行属性的填充。beanName是myDao。

发现要填充的是myService
在这里插入图片描述
再进去inject方法,AutowiredAnnotationBeanPostProcessor#inject
再继续往下走,走到DefaultListableBeanFactory#resolveDependency
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

再继续往下走
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

继续往下走,
在这里插入图片描述

点进去方法,autowireBeanName是myService
descriptor.resolveCandidate(autowiredBeanName, type, this);
点进去后发现里面调用的是getBean,beanName是myService
在这里插入图片描述
惊奇的发现,这不是和myDao创建的过程是一样的吗。按照上面的步骤往下,来到,beanName是myService,获取到为空
Object sharedInstance = getSingleton(beanName);
步骤和上面的一模一样,只是beanName换成了myService,然后myService也被实例化了,也被放进去了singletonFactories和singletonsCurrentlyInCreation里面。

继续往下,也是调用属性填充,按照上面步骤一路往下,走到
发现又回到了beanFactory.getBean(beanName)是myDao
在这里插入图片描述
然后我们继续往下走
一直往下点,跑到
在这里插入图片描述
进入getSingleton方法,或者myDao,由于在myDao和myService创建的时候都加进去了singletonsCurrentlyInCreation,allowEarlyReference默认为true,所以可以走到断点的代码,myDao就被获取出来的
在这里插入图片描述

返回的Object作为返回值,一直被返回到了
field.set(bean, value);field就是我们的myDao,value就是我们的myDao实例,至此,myService的myDao属性就创建好了,最后放到
singletonObjects中,mySercice创建好了,然后myService又作为返回值,返回到field.set(bean, value),field就是myService,value就是myService对应的实例,然后myDao也被填充好了属性,放到singletonObjects。然后就解决了循环依赖的问题。
可能文字描述得不太好,试着用一个流程图来描述这个过程:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值