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。然后就解决了循环依赖的问题。
可能文字描述得不太好,试着用一个流程图来描述这个过程: