循环依赖
以及
spring是如何解决循环依赖的
循环依赖
通俗来说
就是beanA中依赖了beanB,beanB中也依赖了beanA。
spring是支持循环依赖的,但是默认只支持单例的循环依赖,如果bean中依赖了原型bean,则需要加上lookup方法。
继续之前的项目,改造了People,User类:
@Component public class People { @Autowired private User user; public People(){ System.out.println("create People"); } }
@Component public class User { @Autowired private People people; public User(){ System.out.println("create User"); } }
People--(依赖)-->User--(依赖)-->People--(依赖)-->User.......,这就形成了循环依赖。
继续进入上篇的preInstantiateSingletons()方法:
进行条件断点:
进入上篇说的getSingleTon()方法:
singletonObjects是spring的单例池,从其中没有拿到bean,singletonObject为null,且isSingletonCurrentlyInCreation()为false。
public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); }
其实这个方法就是去判断该map(singletonCurrentlyInCreation)是否包含该bean?(这里是people)。
这个方法通俗意思就是 “该bean是否在创建过程中?”
先不管这个意思,继续往下走。
spring创建对象前还会做很多判断,例如是否为原型,是否抽象?
这里的getSingleton(String beanName, ObjectFactory<?> singletonFactory)是重载,与之前的getSingleton(String beanName, boolean allowEarlyReference)不同。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }
此方法把 “people”放入singletonsCurrentlyInCreation中,那么isSingletonCurrentlyInCreation("people")这时为true。
进入lambda表达式 createBean()
create People Object ----注入依赖发现依赖User--->create User Object---发现依赖People---create People Object---发现isSingletonCurrentlyInCreation(beanName)为true,表示正在创建People:
然后才会执行里面的代码:
allowEarlyReference 是否允许从singletonFactories中通过getObject拿到对象,也就是执行if中的方法。
我们看一下singletonObjects(一级缓存),earlySingletonObjects(二级缓存),singletonFactories(三级缓存)。
AbstractAutowireCapableBeanFactory#doCreateBean()中:
这时候存进去的并不是完整的bean:
但是可以供User依赖注入了,这也就是spring对循环依赖的解决。