当两个bean互相依赖,或者多个bean相互依赖并形成一个环状结构的时候,就形成了循环依赖的问题。例如下图: 关于bean的实例化过程,我在spring源码学习_bean的实例化过程中有详细讲解,这里直接说结论。 ① bean在实例化时,spring首先会找到其指定的构造方法,生成这个bean的java对象。此时bean只是单纯的java对象,其中的依赖并没有被注入。这个阶段的bean我们可以理解为是半成品的bena或是早产的bean。 ② 对象生成后,spring就会在spring容器中获取其依赖的对象,并将依赖对象赋值给属性。如果该依赖在spring容器中不存在,则先实例化这个依赖。 我们以上图的第一个情况为例。spring先实例化A,生成了A类的对象,在第二步注入属性时,发现spring容器中并没有B,则转去实例化B。B的对象创建后,又会尝试在Spring容器中寻找A,结果当然是找不到的。因为A现在还是半成品,并不是真正的bean,也没有被放入spring容器中。所以这时spring又得去实例化A。这样就形成了一个死循环,导致这两个bean永远都没法实例化。 尽管我们在实际开发中会避免设计出如此糟糕的依赖关系,但是spring依然为帮我们解决了这个问题。下面,我们就通过源码看看spring是如何解决的。 这里只贴出doGetBean方法中与循环依赖相关的代码 源码中出现了两个getSingleton方法,第一个getSingleton的功能是从缓存中获取bean。如果这个bean是第一次被实例化,那就一定获取不到。第二个 的功能在于创建这个bean。所以这段代码整体的逻辑就是,如果缓存中存在这个bean,则直接返回,如果没有,则创建一个新的实例。 这里咋一看,好像和循环依赖并没有太大的关系,但是深入看看第一个getSingleton方法的实现,发现其并不是从spring容器中取对象这么简单。 重点看第二个重载方法的实现。spring显然不只是单纯的从单例池中拿对象。在spring容器中没有这个bean存在,且isSingletonCurrentlyInCreation判断为true时,spring容器会尝试从singletonFactories获取一个工厂并通过这个工厂构建出一个对象。 那么问题就来了 顺着这个线索,我们继续看第二个 getSingleton 方法。 这个getSingleton方法主要功能就是调用传入的单例工厂中的getObject方法去创建这个bean的实例。并在创建实例之前,把这个bean标记为正在创建状态(装入singletonsCurrentlyInCreation容器中)。 所以当一个bean第一次被创建时,他并不是正在创建状态。进而会进入到第二个getSingleton方法中,创建这个bean的新实例,并被标记为正在创建状态。 上面提到的第一个问题已经解决,现在进入到bena的创建过程,寻找后两个问题的答案。 来到 doCreateBean方法,这个依然只贴出与循环依赖相关的代码 可以看到,单例bena在实例化成为半成品后,向singletonFactories中注册了一个对象工厂,并通过lambda表达式,将工厂中getObject方法的实现指向到了getEarlyBeanReference方法。 现在来重新回顾一下A和B两个类互相依赖时,这两个类的实例化过程。 当A第一次被创建时,他并不是正在创建状态。进而会进入到第二个getSingleton方法中,创建这个bean的新实例,并被标记为正在创建状态。 A的实例创建完毕后,向singletonFactories中注册了一个对象工厂,然后尝试自动注入B。此时的B实例在spring容器中并不存在,则调用getBean方法获取B的实例。 由于B也是第一次被创建,则相同的步骤进到第二个getSingleton方法中。被标记为正在创建状态后,创建了B的实例,向singletonFactories中注册一个对象工厂,然后B又开始尝试自动注入A对象。A此时还没完成属性的注入,所以spring容器中找不到。就再次调用getBean方法获取A的实例。 这次则是A的第二次创建过程,他已经被标记为正在创建状态,且在singletonFactories中有他注册的对象工厂。所以在第一个getSingleton方法中,就能获取到A注册的对象工厂,进而获取到其生产的对象。并将这个对象作为A的实例返回。 B获取到A的实例后,B的装配过程顺利完成。进行初始化之后,B成为一个真正的bean。此时A也就获取到了B的实例,进而A的实例化也完成了。 到了这里,循环依赖的死循环问题就已经解决了。但还有个问题没解决,getEarlyBeanReference方法给我们返回的是一个什么样的对象,这个对象为何可以代替真实的bean。 到了这里就是真破案了。在第二次获取A的实例时,第一个getSingleton方法返回的就是A的半成品对象。 由于在所有bean都是单例的情况下,A中依赖的B对象和B本身是同一个对象,B中依赖的A对象和A本身也是同一个对象。 把A的半成品注入给B,B完成了实例化过程。此时A所依赖的B就是这个实例化完成的B,A也就完成了实例化。有点绕。 换一种情况,如果我们在原型bean的情况下,每次调用getBean方法返回的bean都应该是一个全新的bean。第二次获取A时,就没办法将第一次的半成品返回,这个死循环也就将一直进行下去。 还有一种情况,当我们不是属性注入,而是构造器注入时。我们在对象的创建阶段就会被卡住,就更不谈半成品bean的返回了,所以构造器注入的循环依赖也是无法解决的。 最后是spring解决循环依赖的流程图
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { Object bean; //这里尝试直接从缓存中获取bean Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else{ //缓存中没有,则创建这个bean if (mbd.isSingleton()) { //这里通过lambda表达式,传入了一个对象工厂 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) {....} }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } } return (T) bean; }
public Object getSingleton(String beanName) { //调用另一个重载的getSingleton方法 return getSingleton(beanName, true); } protected Object getSingleton(String beanName, boolean allowEarlyReference) { //首先尝试从spring容器中获取bean实例 Object singletonObject = this.singletonObjects.get(beanName); //如果容器中没有,且这个单例bean处于正在创建状态 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { //从一个早产的单例对象池中获取bean singletonObject = this.earlySingletonObjects.get(beanName); //如果依然没有,且允许被提前引用的话 if (singletonObject == null && allowEarlyReference) { //从单例工厂池中获取到一个对象工厂 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { //通过对象工厂构建单例对象 singletonObject = singletonFactory.getObject(); //将构建出的对象,放入earlySingletonObjects中 //显然earlySingletonObjects是一个缓存,下次可以就直接冲这个容器中拿到对象,而不需要工厂再次构建 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { //避免多线程问题,又一次尝试从单例池中获取 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { //创建的前置处理,将这个bean标记为正在创建状态 beforeSingletonCreation(beanName); try { //调用传入工厂的getObject方法,创建对象 singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) {......} catch (BeanCreationException ex) {......} finally {......} } return singletonObject; } } protected void beforeSingletonCreation(String beanName) { //将bean标记为正在创建状态 if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { //创建这个bena的实例 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } //获取到bena的实例,这里的实例是半成品的bean,还没有被注入过属性 final Object bean = instanceWrapper.getWrappedInstance(); //bean是单例的,且是正在创建的,且allowCircularReferences为true //前两点确定为true了,allowCircularReferences是在本类中初始值为true的一个属性 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { //这里就向singletonFactories中添加了属性 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } try { //装配bean,这里会自动注入bean的所有依赖 //若依赖在spring容器中不存在,则先创建这个依赖实例 populateBean(beanName, mbd, instanceWrapper); } } protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { //再次确认了单例池中没有这个bean if (!this.singletonObjects.containsKey(beanName)) { //向singletonFactories中注册了传入的工厂 this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { //注意,这里传入的bean是半成品bean Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; //掉用getEarlyBeanReference方法获取 exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; } public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { //直接就把半成品bean返回了 return bean; }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算