乐趣区

关于spring:SpringIoC源码分析二依赖注入依赖循环

书接上文我对 IoC 感兴趣的 2 个点别离是

  • IoC 是怎么获取 bean 信息,并治理 bean 的
  • IoC 引以为豪的依赖注入

    • IoC 是怎么解决循环依赖的(没错齐全是因为网上说面试爱问)

    当初曾经解决了第一个问题了,上面来剖析下第二个问题 – 依赖注入

依赖注入简略来说就是本人创建对象交给 Spring 容器治理。那必定就有以下几个步骤了

  1. 创建对象
  2. 将对象所依赖的对象注入进来
  3. 怎么解决循环依赖的问题的
    本篇也将围绕着三点开展了。
    ps: 源码剖析乃集体总结,如果有任何不对的中央,欢送分割我探讨

创建对象

在上一篇中曾经理解到了 Spring 是如何获取 bean 的各项信息,并把信息存储在 DefaultListableBeanFactory 中了。

此时 Spring 还未初始化实现还记得 AbstractApplicationContext#refresh 办法么。

他会在 finishBeanFactoryInitialization 中创建对象

// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有残余的(非提早初始化)单例。finishBeanFactoryInitialization(beanFactory);
@Override
public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in" + this);
   }

   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 形象,非单例,不是提早加载的过滤
         if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               if (isEagerInit) {getBean(beanName);
               }
            }
         }
         else {getBean(beanName);// 一般 bean 进入这个办法
         }
      }
   }

   // Trigger post-initialization callback for all applicable beans... 为所有实用的 bean 触发初始化后回调
   for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();
               return null;
            }, getAccessControlContext());
         }
         else {smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

随后会进入 AbstractBeanFactory#doGetBean, 他是十分外围的一个办法, 大抵流程如下,先从本容器中查问,没有,就去父容器查问,以此类推。查到了,就去曾经创立的 bean 中singletonObjects(key 为 beanName,value 为创立好的 bean) 中寻找,有就间接返回,找不到就再创立,能够了解为,调用这个办法肯定能获取到须要的 bean。

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.|查问缓存中是否
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean'" + beanName +
                  "'that is not fully initialized yet - a consequence of a circular reference");
         }
         else {logger.trace("Returning cached instance of singleton bean'" + beanName + "'");
         }
      }
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.| 查看是否能在以后 BeanFactory 中获得须要的 Bean。没有找到就去父容器去取
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
         }
         // 如果以后 beanFactory 中有 bean
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      if (!typeCheckOnly) {markBeanAsCreated(beanName);
      }

      try {
         // 依据 BeanName 获取 BeanDefinition
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.| 获取以后 bean 依赖的 bean
         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);
               }
            }
         }

         // Create bean instance.
         if (mbd.isSingleton()) {//TODO 创立 bean,配置 bean 外围办法
            sharedInstance = getSingleton(beanName, () -> {
               try {return createBean(beanName, mbd, args);// 创立 bean
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }
         // 创立 property bean 的中央
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         else {String scopeName = mbd.getScope();
            if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean'" + beanName + "'");
            }
            Scope scope = this.scopes.get(scopeName);
            if (scope == null) {throw new IllegalStateException("No Scope registered for scope name'" + scopeName + "'");
            }
            try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);
                  try {return createBean(beanName, mbd, args);
                  }
                  finally {afterPrototypeCreation(beanName);
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope'" + scopeName + "'is not active for the current thread; consider" +
                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }
   // 此时 bean 曾经蕴含了依赖关系的 bean
   // Check if required type matches the type of the actual bean instance.|查看所需类型是否与理论 bean 实例的类型匹配
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      }
      catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean'" + name + "'to required type'" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

而后会调用AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean. 持有创立进去的 Bean 对象
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {// 单例,先把缓存中的同名 Bean 革除
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   //TODO 理论创立 bean
   if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}

   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {
         try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean'" + beanName +
               "'to allow for resolving potential circular references");
      }
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.|依赖注入在这里产生
   Object exposedObject = bean;
   try {populateBean(beanName, mbd, instanceWrapper);
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }

   if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);
               }
            }
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name'" + beanName + "'has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been" +
                     "wrapped. This means that said other beans do not use the final version of the" +
                     "bean. This is often the result of over-eager type matching - consider using" +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   try {registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

如果该 bean 没有任何依赖会很顺利的通过反射创立,调用如下办法。

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {Assert.notNull(ctor, "Constructor must not be null");
   try {ReflectionUtils.makeAccessible(ctor);
      if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {return KotlinDelegate.instantiateClass(ctor, args);
      }
      else {Class<?>[] parameterTypes = ctor.getParameterTypes();
         Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
         Object[] argsWithDefaultValues = new Object[args.length];
         for (int i = 0 ; i < args.length; i++) {if (args[i] == null) {Class<?> parameterType = parameterTypes[i];
               argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
            }
            else {argsWithDefaultValues[i] = args[i];
            }
         }
         return ctor.newInstance(argsWithDefaultValues);
      }
   }
   ... 略
}

最初把创立好的 bean,增加进 map 中

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

依赖注入

依赖注入呢,会在创立实现后多一步

如果有 bean,有须要依赖注入的属性

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {if (pvs.isEmpty()) {return;}

   if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
   }

   MutablePropertyValues mpvs = null;
   List<PropertyValue> original;

   if (pvs instanceof MutablePropertyValues) {mpvs = (MutablePropertyValues) pvs;
      if (mpvs.isConverted()) {
         // Shortcut: use the pre-converted values as-is.
         try {bw.setPropertyValues(mpvs);
            return;
         }
         catch (BeansException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
         }
      }
      original = mpvs.getPropertyValueList();}
   else {original = Arrays.asList(pvs.getPropertyValues());
   }

   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {converter = bw;}
   //BeanDefinitionValueResolver 对 BeanDefinition 的解析是在这个 valueResolver 中实现
   BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

   // Create a deep copy, resolving any references for values.
   List<PropertyValue> deepCopy = new ArrayList<>(original.size());
   boolean resolveNecessary = false;
   for (PropertyValue pv : original) {if (pv.isConverted()) {deepCopy.add(pv);
      }
      else {String propertyName = pv.getName();
         Object originalValue = pv.getValue();
         if (originalValue == AutowiredPropertyMarker.INSTANCE) {Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
            if (writeMethod == null) {throw new IllegalArgumentException("Autowire marker for property without write method:" + pv);
            }
            originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
         }
         Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);// 获取到的 bean 对象
         Object convertedValue = resolvedValue;
         // 判断是否有 set 办法
         boolean convertible = bw.isWritableProperty(propertyName) &&
               !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
         if (convertible) {convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
         }
         // Possibly store converted value in merged bean definition,
         // in order to avoid re-conversion for every created bean instance.
         if (resolvedValue == originalValue) {if (convertible) {pv.setConvertedValue(convertedValue);
            }
            deepCopy.add(pv);
         }
         else if (convertible && originalValue instanceof TypedStringValue &&
               !((TypedStringValue) originalValue).isDynamic() &&
               !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {pv.setConvertedValue(convertedValue);
            deepCopy.add(pv);
         }
         else {
            resolveNecessary = true;
            deepCopy.add(new PropertyValue(pv, convertedValue));
         }
      }
   }
   if (mpvs != null && !resolveNecessary) {mpvs.setConverted();
   }

   // Set our (possibly massaged) deep copy.
   try {
      // 依赖注入产生的中央
      bw.setPropertyValues(new MutablePropertyValues(deepCopy));
   }
   catch (BeansException ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
   }
}

最终会调用 set 办法,进行注入

//set 办法注入
@Override
public void setValue(@Nullable Object value) throws Exception {
   Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
         ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
         this.pd.getWriteMethod());
   if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {ReflectionUtils.makeAccessible(writeMethod);
         return null;
      });
      try {AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
               () -> writeMethod.invoke(getWrappedInstance(), value), acc);
      }
      catch (PrivilegedActionException ex) {throw ex.getException();
      }
   }
   else {ReflectionUtils.makeAccessible(writeMethod);
      writeMethod.invoke(getWrappedInstance(), value);
   }
}

@Autowired呢略微有点不同
它是在此处进行解决。

注解是通过 field 间接设置值AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Field field = (Field) this.member;
   Object value;
   if (this.cached) {
      try {value = resolvedCachedArgument(beanName, this.cachedFieldValue);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Unexpected removal of target bean for cached argument -> re-resolve
         value = resolveFieldValue(field, bean, beanName);
      }
   }
   else {value = resolveFieldValue(field, bean, beanName);
   }
   if (value != null) {ReflectionUtils.makeAccessible(field);
      field.set(bean, value);
   }
}

循环依赖

测试代码如下

@Component
public class Father {
   @Autowired
   private Son son;

   public void say(){son.say();
      System.out.println("say hello");
   }
}
@Component
public class Son {
   @Autowired
   private Father father;

   public void say(){System.out.println("abcdefg");
   }
}

如何解决循环依赖呢?spring 会在创立反射创立完 bean 之后, 依赖注入之前,把 bean 的援用先缓存到 singletonFactories

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

着有什么用呢

当解析类中的 bean 的时候会调用 getBean 获取,就会进入到 DefaultSingletonBeanRegistry#getSingleton(String, boolean) 尝试获取 bean,这外面 `
singletonsCurrentlyInCreation
会记录正在创立的 bean,例如下面我写的例子,father 须要 son,son 又须要 father,不论哪一个先创立,举个例子,father 先创立,在须要注入的时候,发现 son 没有创立,这个时候,开始创立 son,son 在注入的时候,又须要 father,此时 father 还未创立完,这时候 singletonFactories 就起到作用了,singletonFactories存的是创立实现的,然而还注入实例的对象,然而 father 的援用不会变,只是还没有给 son 赋值。这时候就把 father 的援用先给 son,son 创立实现,在赋值给 father。大抵就是这么一个过程。创立实现,再把 singletonFactories 外面的删除,对立贮存到singletonObjects`。

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock|疾速检没有锁的现有实例
   Object singletonObject = this.singletonObjects.get(beanName);
   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) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {singletonObject = singletonFactory.getObject();
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

创立实现当前删除,对立存储到 singletonObjects 中。

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);
   }
}
退出移动版