likes
comments
collection
share

Spring源码探索-核心原理上(IoC、DI)

作者站长头像
站长
· 阅读数 34

IoC

这里我们只关注xml配置方式不管注解配置方法

配置文件路径解析时序图

Spring源码探索-核心原理上(IoC、DI)

配置文件路径解析核心代码

Spring源码探索-核心原理上(IoC、DI) 首先从applicationContext构造方法的入参就可以知道如果多个配置文件的话可以直接传一个字符串数组

protected String parseStringValue(String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
    int startIndex = value.indexOf(this.placeholderPrefix);
    if (startIndex == -1) {
        return value;
    } else {
        StringBuilder result = new StringBuilder(value);

        while(startIndex != -1) {
            int endIndex = this.findPlaceholderEndIndex(result, startIndex);
            if (endIndex != -1) {
                String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
                String originalPlaceholder = placeholder;
                if (visitedPlaceholders == null) {
                    visitedPlaceholders = new HashSet(4);
                }

                if (!((Set)visitedPlaceholders).add(placeholder)) {
                    throw new IllegalArgumentException("Circular placeholder reference '" + placeholder + "' in property definitions");
                }

                placeholder = this.parseStringValue(placeholder, placeholderResolver, (Set)visitedPlaceholders);
                String propVal = placeholderResolver.resolvePlaceholder(placeholder);
                if (propVal == null && this.valueSeparator != null) {
                    int separatorIndex = placeholder.indexOf(this.valueSeparator);
                    if (separatorIndex != -1) {
                        String actualPlaceholder = placeholder.substring(0, separatorIndex);
                        String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
                        propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
                        if (propVal == null) {
                            propVal = defaultValue;
                        }
                    }
                }

                if (propVal != null) {
                    propVal = this.parseStringValue(propVal, placeholderResolver, (Set)visitedPlaceholders);
                    result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Resolved placeholder '" + placeholder + "'");
                    }

                    startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
                } else {
                    if (!this.ignoreUnresolvablePlaceholders) {
                        throw new IllegalArgumentException("Could not resolve placeholder '" + placeholder + "' in value "" + value + """);
                    }

                    startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
                }

                ((Set)visitedPlaceholders).remove(originalPlaceholder);
            } else {
                startIndex = -1;
            }
        }

        return result.toString();
    }
}

上述代码是对单个字符串进行解析,我们可以看到Spring处理可以使用传递数组的方式支持多配置文件,也可以只传一个字符串通过固定的模板解析出多个配置文件代码中可以知道前缀是 ${后缀是}中间的间隔是:

初始化时序图

Spring源码探索-核心原理上(IoC、DI)

核心类

ApplicationContext

ApplicationContextBeanFactory 的子接口,也被称为 Spring 上下文. ApplicationContextspring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。 另外,它增加了企业所需要的功能,比如,从属性文件中解析文本信息和将事件传递给所指定的监听器 Spring源码探索-核心原理上(IoC、DI)

BeanDefinition

类似于Bean的描述文件,其中记录了Bean所有的信息比如:它里面包含了Bean指向的类、是否单例、是否懒加载、Bean的依赖关系等相关的属性 Spring源码探索-核心原理上(IoC、DI)

BeanDefinitionReader

BeanDefinitionReader是一个简单的接口,是用于读取Spring配置文件的内容,并转换为BeanDefinition。一共有三个实现类: Spring源码探索-核心原理上(IoC、DI) 分别是针对不同的配置方式使用不同的策略读取

初始化核心方法

refresh()
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
         contextRefresh.end();
      }
   }
}

这里面比较核心的方法就是obtainFreshBeanFactory

obtainFreshBeanFactory()

这个方法负责了BeanFactory的初始化、Bean的加载和注册等事件

obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   //核心:创建BeanFactory的方法
   refreshBeanFactory();
   return getBeanFactory();
}

refreshBeanFactory方法中创建了BeanFactory

refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException {
   // 判断当前ApplicationContext是否存在BeanFactory,如果存在的话就销毁所有 Bean,关闭 BeanFactory
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      //这里开始加载BeanDefinition
      loadBeanDefinitions(beanFactory);
      this.beanFactory = beanFactory;
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   //这里创建了BeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   //初始化BeanDefinitionReader
   initBeanDefinitionReader(beanDefinitionReader);
   //继续往下
   loadBeanDefinitions(beanDefinitionReader);
}

接下来开始进入到readerloadBeanDefinitions方法中来(上文我们也说过了BeanDefinition的加载是由BeanDefinitionReader来完成的)一直往下跟回来到一个doLoadBeanDefinitions方法中来

doLoadBeanDefinitions()

这也是一个比较重要的方法,在这里会将我们的配置文件转成一个Document树有点类似于前端的dom树,js是解释性语言最终会将所有的标签转成一个dom树 Spring源码探索-核心原理上(IoC、DI) 至此Bean配置信息的载入就完成了。最后一步就是注册其实注册就是将 Document转换成 BeanDefinition然后存在IoC容器中(也就是载入内存中)

doRegisterBeanDefinitions()

这里面有个核心的方法 parseDefaultElement

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // Register the final decorated instance.
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error("Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}

可以发现最终注册Bean配置信息是在BeanDefinitionReaderUtils工具类中实现的

public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // Register bean definition under primary name.
   String beanName = definitionHolder.getBeanName();
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // Register aliases for bean name, if any.
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String alias : aliases) {
         registry.registerAlias(beanName, alias);
      }
   }
}

是在DefaultListableBeanFactory类中的registerBeanDefinition方法实现了 BeanDefinition的注册

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {

   Assert.hasText(beanName, "Bean name must not be empty");
   Assert.notNull(beanDefinition, "BeanDefinition must not be null");

   if (beanDefinition instanceof AbstractBeanDefinition abd) {
      try {
         abd.validate();
      }
      catch (BeanDefinitionValidationException ex) {
         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
               "Validation of bean definition failed", ex);
      }
   }

   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   if (existingDefinition != null) {
      if (!isAllowBeanDefinitionOverriding()) {
         throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      }
      else if (existingDefinition.getRole() < beanDefinition.getRole()) {
         // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
         if (logger.isInfoEnabled()) {
            logger.info("Overriding user-defined bean definition for bean '" + beanName +
                  "' with a framework-generated bean definition: replacing [" +
                  existingDefinition + "] with [" + beanDefinition + "]");
         }
      }
      else if (!beanDefinition.equals(existingDefinition)) {
         if (logger.isDebugEnabled()) {
            logger.debug("Overriding bean definition for bean '" + beanName +
                  "' with a different definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Overriding bean definition for bean '" + beanName +
                  "' with an equivalent definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
      if (isAlias(beanName)) {
         if (!isAllowBeanDefinitionOverriding()) {
            String aliasedName = canonicalName(beanName);
            if (containsBeanDefinition(aliasedName)) {  // alias for existing bean definition
               throw new BeanDefinitionOverrideException(
                     beanName, beanDefinition, getBeanDefinition(aliasedName));
            }
            else {  // alias pointing to non-existing bean definition
               throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                     "Cannot register bean definition for bean '" + beanName +
                     "' since there is already an alias for bean '" + aliasedName + "' bound.");
            }
         }
         else {
            removeAlias(beanName);
         }
      }
      if (hasBeanCreationStarted()) {
         // Cannot modify startup-time collection elements anymore (for stable iteration)
         synchronized (this.beanDefinitionMap) {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
            updatedDefinitions.addAll(this.beanDefinitionNames);
            updatedDefinitions.add(beanName);
            this.beanDefinitionNames = updatedDefinitions;
            removeManualSingletonName(beanName);
         }
      }
      else {
         // Still in startup registration phase
         this.beanDefinitionMap.put(beanName, beanDefinition);
         this.beanDefinitionNames.add(beanName);
         removeManualSingletonName(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }

   if (existingDefinition != null || containsSingleton(beanName)) {
      resetBeanDefinition(beanName);
   }
   else if (isConfigurationFrozen()) {
      clearByTypeCache();
   }
}

至此,Bean 配置信息中配置的 Bean 被解析过后,已经注册到 IoC 容器中,被容器管理起来,真正完 成了 IoC 容器初始化所做的全部工作。现在IoC 容器中已经建立了整个 Bean 的配置信息,这些 BeanDefinition 已经可以使用,并且可以被检索,IoC容路的作用就是对这些注册的 Bean定义信息进行处理和维护。这些的注册的 Bean 定义信息是 IoOC 容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。

需要注意的是这里是完成了BeanDefinition加载注册对于全部都是懒加载的Bean来说IoC容器已经完成了初始化(我们这里就默认所有的Bean都是懒加载的下文讲DI中会将具体的初始化流程)

DI

入口就是getBean方法下文分析默认bean懒加载的还没有实例化的

时序图

Spring源码探索-核心原理上(IoC、DI)

核心类

BeanFactory

是最最基础的 IoC 容器,它提供了一个 IoC 容器所需的基本功能 Spring源码探索-核心原理上(IoC、DI)

FactoryBean

BeanFactory是生产 bean的工厂而 FactoryBean本质上还是一个 Bean还是由 BeanFactory生产而来,但是 FactoryBean又区别于普通的 Bean FactoryBean像是Bean的包装类,有些Bean初始化流程很复杂不能简单的通过反射调用实例化所以这个时候我们就可以自定义一个FactoryBeangetObject方法中实现复杂类的初始化,实际在getBean的时候就是使用的FactoryBean中的getObject方法返回对应的实例

BeanWrapper

就是bean的包装类,实际存到IoC的bean并不是类的原始对象而是包装类

核心代码

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

     String beanName = transformedBeanName(name);
     Object beanInstance;

     // 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 + "'");
           }
        }
        beanInstance = 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 parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
           // Not found -> check parent.
           String nameToLookup = originalBeanName(name);
           if (parentBeanFactory instanceof AbstractBeanFactory abf) {
              return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
           }
           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);
        }

        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
              .tag("beanName", name);
        try {
           if (requiredType != null) {
              beanCreation.tag("beanType", requiredType::toString);
           }
           RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
           checkMergedBeanDefinition(mbd, beanName, args);

           // Guarantee initialization of beans that the current bean depends on.
           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()) {
              sharedInstance = getSingleton(beanName, () -> {
                 try {
                    return createBean(beanName, mbd, args);
                 }
                 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;
                 }
              });
              beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
           }

           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);
              }
              beanInstance = 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);
                    }
                 });
                 beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
              }
              catch (IllegalStateException ex) {
                 throw new ScopeNotActiveException(beanName, scopeName, ex);
              }
           }
        }
        catch (BeansException ex) {
           beanCreation.tag("exception", ex.getClass().toString());
           beanCreation.tag("message", String.valueOf(ex.getMessage()));
           cleanupAfterBeanCreationFailure(beanName);
           throw ex;
        }
        finally {
           beanCreation.end();
        }
     }

     return adaptBeanInstance(name, beanInstance, requiredType);
  }

通过上面对向 loC 容器获取 Bean 方法的分析,我们可以看到在 Spring 中,如果 Bean 定义的单例 模式(Singleton),则容器在创建之前先从缓存中查找,以确保整个容器中只存在一个实例对象。如果 Bean 定义的是原型模式(Prototype),则容器每次都会创建一个新的实例对象。除此之外,Bean 定义 还可以扩展为指定其生命周期范围。

doCreateBean

这个方法就开始实例化 bean

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

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   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.markAsPostProcessed();
      }
   }

   // 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 bce && beanName.equals(bce.getBeanName())) {
         throw bce;
      }
      else {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), 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;
}

createBeanlnstance()方法,生成 Bean 所包含的java 对象实例。 populateBean()方法,对 Bean 属性的依赖注入进行处理。

createBeanlnstance
  protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
     // Make sure bean class is actually resolved at this point.
     Class<?> beanClass = resolveBeanClass(mbd, beanName);

     if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
     }

     Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
     if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
     }

     if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
     }

     // Shortcut when re-creating the same bean...
     boolean resolved = false;
     boolean autowireNecessary = false;
     if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
           if (mbd.resolvedConstructorOrFactoryMethod != null) {
              resolved = true;
              autowireNecessary = mbd.constructorArgumentsResolved;
           }
        }
     }
     if (resolved) {
        if (autowireNecessary) {
           return autowireConstructor(beanName, mbd, null, null);
        }
        else {
           return instantiateBean(beanName, mbd);
        }
     }

     // Candidate constructors for autowiring?
     Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
     if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
           mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
     }

     // Preferred constructors for default construction?
     ctors = mbd.getPreferredConstructors();
     if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
     }

     // No special handling: simply use no-arg constructor.
     return instantiateBean(beanName, mbd);
  }
  ```
  ```
  protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
     try {
        Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
     }
     catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
     }
  }

从源码中可以看创建实例是根据指定的初始化策略,使用简单工厂、工厂方法或者容器的自动装配特性生成 Java 实例对象. 对使用工厂方法和自动装配特性的 Bean 的实例化相当比较清楚,调用相应的工厂方法或者参数匹配的构造方法即可完成实例化对象的工作,但是对于我们最常使用的默认无参构這方法就需要使用相应的初始化策(JDK反射机制或者 CGiib)来进行初始化了,在方法 getlnstantiationStrategy()中获取对应的策略,然后再策略的instantiate方法中实现。 至此实例的初始化就完成了

populateBean

这里开始依赖注入,这里的逻辑可以分为两种:

  1. 对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性。
  2. 对于非集合类型的属性,大量使用了JDK的反射机制,通过属性的 getter()方法获取指定属性注入以前的值,同时调用属性的 setter()方法为属性设置注入后的值。

循环依赖问题

造成循环依赖的原因

如下代码所示:

@Service
public class TuDou {

    @Autowired
    private TuDou2 tuDou2;
    @Override
    public String toString() {
        return super.toString();
    }
}
@Service
public class TuDou2 {
    @Autowired
    private TuDou tuDou;
    @Override
    public String toString() {
        return super.toString();
    }
}

看一下对应的类图: Spring源码探索-核心原理上(IoC、DI) 此时就会造成循环引用

Spring解决方案

一下几种方式是不能解决循环依赖的:

  1. 多例的情况(就是每次都去创建新的对象)
  2. 构造器注入

三级缓存的结构:

  1. singletonObjects:一级缓存,存储单例对象,Bean 已经实例化,走过完整生命周期的Bean
  2. earlySingletonObjects:二级缓存,存储 singletonObject,这个 Bean 实例化了,但是还没有依赖注入也就是半成品
  3. singletonFactories:三级缓存,存储的是 Bean 工厂对象,可以用来生成半成品的 Bean

解决循环依赖的步骤如下: Spring源码探索-核心原理上(IoC、DI) 这里有个疑问就是为什么有三级缓存。 三级缓存主要是解决被代理类的情况。 如果一个bean需要被代理只有二级缓存的情况下注入的是原始对象而不是代理对象,三级缓存的意义就是在依赖注入的时候会判断bean是否需要被代理如果需要则提前获取代理对象(代理对象在依赖注入之后BeanPostProcessor中生成的,这里相当于提前获取)

再来说明一下上面两种情况为什么不能解决循环依赖:

  1. 多例的情况,如果是多例A需要B则B创建一下,但是B需要A,A又创建以此循环了没办法解决
  2. 构造方法注入,应为就算有了三级缓存解决循环依赖还是需要先将原始对象创建出来的,构造方法中缺少对应的参数必然是没办法执行的所以也没有办法解决循环依赖
转载自:https://juejin.cn/post/7218847310309687333
评论
请登录