Spring源码-doCreateBean

news2024/11/16 0:21:57

先看段代码:

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


    if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;


    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
    }
    try {
      mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
          beanName, "Validation of method overrides failed", ex);
    }


    try {
      /**1:当经历过resolveBeforeInstantiation方法后,
      程序有两个选择,如果创建了代理或者说重写了
      InstantiationAwareBeanPostProcessor的
      postProcessBeforeInstantiation方法并在方法
      postProcessBeforeInstantiation中改变了bean,则直接返回就可以了,
      否则需要进行常规bean的创建。
      */
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
        return bean;
      }
    }
    catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
          "BeanPostProcessor before instantiation of bean failed", ex);
    }


    try {
      //常规bean的创建
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      throw ex;
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
  }

本篇文章主要分析doCreateBean方法,这个是常规bean的创建,代码注释安排:

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


    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
      //1.如果是单例则需要首先清除缓存
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
      //2.根据指定bean使用对应的策略创建新的实例,例如:工厂方法、构造函数自动注入、简单初始化
      instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final 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 {
          //3.bean合并后的处理,Autowired注解正是通过此方法实现诸如类型的预解析
          applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        }
        catch (Throwable ex) {
          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "Post-processing of merged bean definition failed", ex);
        }
        mbd.postProcessed = true;
      }
    }


    //4.是否需要提早曝光:是单例 并且 允许循环依赖 并且 当前bean正在创建中,检测循环依赖
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
        logger.debug("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
      }
      //addSingletonFactory:为了避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂缓存
      //getEarlyBeanReference:对bean再一次依赖引用,SmartInstantiationAwareBeanPostProcessor,其中我们熟知的AOP就是在这里将advice动态织入bean中,若没有则直接返回bean,不做任何处理
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }


    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
      //5.对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean
      populateBean(beanName, mbd, instanceWrapper);
      //5下.调用初始化方法,比如init-method,初始化bean
      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) {
      //6.earlySingtonReference只有在检测到有循环依赖的情况下才会不为空
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
        if (exposedObject == bean) {
          //如果exposedObject没有在初始化方法中被改变,也就是没有被增强
          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);
            }
          }
          //因为bean创建后其所依赖的bean一定是已经创建的,actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在循环依赖
          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 " +
                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
          }
        }
      }
    }


    // Register bean as disposable.
    try {
      //7.根据scope注册DisposableBean
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
          mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    //8.返回创建好的bean
    return exposedObject;
  }

接下来看下doCreateBean方法的概要思路:

(1)如果是单例则需要首先清除缓存(至于什么时候进行put,现在说为时尚早,以后更到那一篇的时候会说,这里留意下)。

(2)实例化bean,将BeanDefinition转换为BeanWrapper。转换是一个复杂的过程,大概分为这几步:

1.如果存在工厂方法则使用工厂方法进行初始化。

2.一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化。

3.如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行bean的实例化。

(3)MergedBeanDefinitionPostProcessor的应用,bean合并后的处理,Autowired注解正是通过此方法实现诸如类型的预解析。

(4)循环依赖处理。

(5)属性填充,将所有的属性填充到bean的实例中。

(6)循环依赖检查。

(7)注册DisposableBean,如果配置了destroy-method,这里需要注册以便于在销毁的时候调用。

(8)完成创建并返回。

接下来对doCreateBean方法中重要的几步进行分析:

一、首先看createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 解析class
    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);
      }
    }


    // 需要根据参数解析构造函数
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      //构造函数自动注入
      return autowireConstructor(beanName, mbd, ctors, args);
    }


    // No special handling: simply use no-arg constructor.
    //翻一下,没有特殊的处理,简单使用无参构造
    return instantiateBean(beanName, mbd);
  }

概括下createBeanInstance方法做了什么:

(1)mbd.getFactoryMethodName() != null意思就是如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method,那么spring会根据RootBeanDefinition中的配置使用instantiateUsingFactoryMethod方法生成bean的实例。

(2)解析构造函数并进行构造函数的实例化,一个bean可能对应多个构造函数,每个构造函数的参数不同,spring会根据参数个数及类型去判断最终会使用哪个构造函数进行实例化,但是这个判断过程很耗性能,所以这里用了缓存的机制,也就是判断resolvedConstructorOrFactoryMethod(看字面意思就知道:已经被解析的构造函数或者工厂方法)不为空就说明解析过了,直接取出来用就行了,如果缓存中没取到,就需要去解析构造函数,然后存入缓存以便下次使用。

看完createBeanInstance方法后你觉得里面哪个方法比较重要?其中有两个方法肯定给你留下了很深的印象,一个是autowireConstructor,另外一个是instantiateBean,因为最后不管构造函数解析过没解析过,都是走的这俩方法中的其中一个,发现了没?autowireConstructor这个方法是带有参数的实例化,意思就是用有参构造的进行实例化,而instantiateBean这个走的就是默认的无参构造了。

1.1、首先看下autowireConstructor方法

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
      @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {


    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);


    Constructor<?> constructorToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;
    //如果getBean方法调用的时候指定方法参数那么直接使用
    if (explicitArgs != null) {
      argsToUse = explicitArgs;
    }
    else {
      //如果在getBean方法调用的时候没有指定则尝试从配置文件中解析
      Object[] argsToResolve = null;
      //尝试从缓存中获取
      synchronized (mbd.constructorArgumentLock) {
        constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
        if (constructorToUse != null && mbd.constructorArgumentsResolved) {
          // Found a cached constructor...
          //从缓存中取
          argsToUse = mbd.resolvedConstructorArguments;
          if (argsToUse == null) {
            //配置的构造函数参数
            argsToResolve = mbd.preparedConstructorArguments;
          }
        }
      }
      //如果缓存中存在
      if (argsToResolve != null) {
        /**解析参数类型,如给定方法的构造函数是A("1","1"),
        那么通过此方法后就会把配置中的("1","1")转换为(1,1),
        当然,缓存中的值可能是原始值也可能是最终值*/
        argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
      }
    }
    //没有被缓存
    if (constructorToUse == null) {
      // 需要解析构造函数
      boolean autowiring = (chosenCtors != null ||
          mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
      ConstructorArgumentValues resolvedValues = null;


      int minNrOfArgs;
      if (explicitArgs != null) {
        minNrOfArgs = explicitArgs.length;
      }
      else {
        //提取配置文件中配置的构造函数参数
        ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
        //用户承载解析后的构造函数参数的值
        resolvedValues = new ConstructorArgumentValues();
        //能解析到的参数的个数
        minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
      }


      // 获取所有的构造函数
      Constructor<?>[] candidates = chosenCtors;
      if (candidates == null) {
        Class<?> beanClass = mbd.getBeanClass();
        try {
          candidates = (mbd.isNonPublicAccessAllowed() ?
              beanClass.getDeclaredConstructors() : beanClass.getConstructors());
        }
        catch (Throwable ex) {
          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "Resolution of declared constructors on bean Class [" + beanClass.getName() +
              "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
        }
      }
      /**将给定的构造函数排序,
      先public类型的构造函数根据参数数量降序排序,
      然后不是public的构造函数按参数数量降序排序*/
      AutowireUtils.sortConstructors(candidates);
      int minTypeDiffWeight = Integer.MAX_VALUE;
      Set<Constructor<?>> ambiguousConstructors = null;
      LinkedList<UnsatisfiedDependencyException> causes = null;


      for (Constructor<?> candidate : candidates) {
        Class<?>[] paramTypes = candidate.getParameterTypes();


        if (constructorToUse != null && argsToUse.length > paramTypes.length) {
          /**如果已经找到选用的构造函数或者
          需要的参数个数小于当前的构造函数参数个数则终止,
          因为已经按照参数个数降序排列*/
          break;
        }
        if (paramTypes.length < minNrOfArgs) {
          /**当前的构造函数个数小于需要的参数个数,就继续,
          因为构造函数肯定得让这些参数全部传进去啊*/
          continue;
        }


        ArgumentsHolder argsHolder;
        if (resolvedValues != null) {
          //有参数则根据值构造对应参数类型的参数
          try {
            //注释上获取参数的名称
            String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
            if (paramNames == null) {
              //获取参数名称探索器
              ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
              if (pnd != null) {
                //获取指定构造函数的参数名称
                paramNames = pnd.getParameterNames(candidate);
              }
            }
            //根据名称和数据类型创建参数持有者
            argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
                getUserDeclaredConstructor(candidate), autowiring);
          }
          catch (UnsatisfiedDependencyException ex) {
            if (logger.isTraceEnabled()) {
              logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
            }
            // Swallow and try next constructor.
            if (causes == null) {
              causes = new LinkedList<>();
            }
            causes.add(ex);
            continue;
          }
        }
        else {
          // Explicit arguments given -> arguments length must match exactly.
          if (paramTypes.length != explicitArgs.length) {
            continue;
          }
          //构造函数没有参数的情况
          argsHolder = new ArgumentsHolder(explicitArgs);
        }
        //探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
        int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
        // Choose this constructor if it represents the closest match.
        //如果它代表着当前最接近的匹配则选择作为构造函数
        if (typeDiffWeight < minTypeDiffWeight) {
          constructorToUse = candidate;
          argsHolderToUse = argsHolder;
          argsToUse = argsHolder.arguments;
          minTypeDiffWeight = typeDiffWeight;
          ambiguousConstructors = null;
        }
        else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
          if (ambiguousConstructors == null) {
            ambiguousConstructors = new LinkedHashSet<>();
            ambiguousConstructors.add(constructorToUse);
          }
          ambiguousConstructors.add(candidate);
        }
      }


      if (constructorToUse == null) {
        if (causes != null) {
          UnsatisfiedDependencyException ex = causes.removeLast();
          for (Exception cause : causes) {
            this.beanFactory.onSuppressedException(cause);
          }
          throw ex;
        }
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Could not resolve matching constructor " +
            "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
      }
      else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Ambiguous constructor matches found in bean '" + beanName + "' " +
            "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
            ambiguousConstructors);
      }


      if (explicitArgs == null) {
        //将解析的构造函数加入缓存
        argsHolderToUse.storeCache(mbd, constructorToUse);
      }
    }
    try {
      final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
      Object beanInstance;


      if (System.getSecurityManager() != null) {
        final Constructor<?> ctorToUse = constructorToUse;
        final Object[] argumentsToUse = argsToUse;
        beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
            strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
            beanFactory.getAccessControlContext());
      }
      else {
        beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
      }
      //将创建的实例加入BeanWrapper中
      bw.setBeanInstance(beanInstance);
      return bw;
    }
    catch (Throwable ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
          "Bean instantiation via constructor failed", ex);
    }
  }

autowireConstructor有点长,接下来总结下这个方法的大概运行流程:

(1)确定构造函数的参数,分为三步:

1.如果传入的explicitArgs不为空,就可以直接确定参数,因为explicitArgs参数是在调用Bean的时候用户指定的。

2.如果构造函数参数已经记录在缓存里的话,那么可以直接拿来用,这里要注意一点就是缓存中的参数类型不一定是最终类型,如果不是最终类型的话需要转换下类型。

3.如果前两步都获取不到的话就从配置文件配置的构造函数获取,通过BeanDefinition中的getConstructorArgumentValues获取后,再调用resolveConstructorArguments解析得到参数。

(2)确定构造函数,上一步已经确定了构造函数的参数,这一步需要根据这些参数锁定对应的构造函数,匹配的方法就是根据参数个数匹配。

(3)根据确定好的构造函数转换对应的参数类型,比如你的参数是Integer的,但是构造函数需要String的,这时候你得转换成String的才能传入构造函数。

(4)再次验证构造函数,因为有时候就算构造函数,参数名称和类型以及值都确定后也不一定直接锁定构造函数,不同构造函数的参数为父子关系,所以Spring在最后又做了一步验证。

(5)根据实例化策略以及得到得构造函数及构造函数参数实例化Bean。

 

1.2、然后看下instantiateBean方法

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
      Object beanInstance;
      final BeanFactory parent = this;
      if (System.getSecurityManager() != null) {
        beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
            getInstantiationStrategy().instantiate(mbd, beanName, parent),
            getAccessControlContext());
      }
      else {
        beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      }
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
  }

这个方法其实就是利用无参构造对bean进行实例化的,无参构造和有参

构造哪个简单?肯定是无参的了,所以这个方法里就直接对bean进行实例
了。其实仔细看下实例化的方法,是这么一段代码:

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

接下来就看看这个instantiate方法具体是怎么进行实例化的:

@Override
  public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    /** 
    如果有需要覆盖或者动态替换的方法则当然需要使用cglib进行动态代理,
    因为可以在创建代理的同时将动态方法织入类中,但是如果没有需要动态改变
    的方法,为了方便直接使用反射就可以了
    */
    if (!bd.hasMethodOverrides()) {
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
        constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
        if (constructorToUse == null) {
          final Class<?> clazz = bd.getBeanClass();
          if (clazz.isInterface()) {
            throw new BeanInstantiationException(clazz, "Specified class is an interface");
          }
          try {
            if (System.getSecurityManager() != null) {
              constructorToUse = AccessController.doPrivileged(
                  (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
            }
            else {
              constructorToUse = clazz.getDeclaredConstructor();
            }
            bd.resolvedConstructorOrFactoryMethod = constructorToUse;
          }
          catch (Throwable ex) {
            throw new BeanInstantiationException(clazz, "No default constructor found", ex);
          }
        }
      }
      return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
      // Must generate CGLIB subclass.
      return instantiateWithMethodInjection(bd, beanName, owner);
    }
  }

大概总结下instantiate这个方法,首先判断

!bd.hasMethodOverrides(),如果是true,说明用户没有使用

replace或lookup的配置方法,这时候就直接使用反射,简单快捷,但是
如果使用了这两个特性,就需要使用动态代理的方式将包含两个特性所对应
的逻辑拦截增强器设置进去。

二、接下来看doCreateBean方法中的第四个注释

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
        logger.debug("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
      }
      //addSingletonFactory:为了避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂缓存
      //getEarlyBeanReference:对bean再一次依赖引用,SmartInstantiationAwareBeanPostProcessor,其中我们熟知的AOP就是在这里将advice动态织入bean中,若没有则直接返回bean,不做任何处理
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

earlySingletonExposure表示是否提前曝光,有三个条件决定这个

变量的值,当前bean的scope是单例并且允许循环依赖并且当前单例bean正
在被创建。然后往下看,最关键的一句代码来了,getEarlyBeanReference这个方法是什么?你还记得循环依赖怎么解决的
吗?是不是从singletonFactories中取出来一个singletonFactory

,然后调用了singletonFactory的getObject方法,其中这个getObject
方法就是这个getEarlyBeanReference,这里java8的lambda表达式有点
迷惑性,addSingletonFactory用jdk7表示如下:

      addSingletonFactory(beanName, new ObjectFactory(){
        public Object getObject() throws BeansException{
          return getEarlyBeanReference(beanName, mbd, bean);
        }
      });

然后看下getEarlyReference方法的代码:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
          SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
          exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
        }
      }
    }
    return exposedObject;
  }

看见没,循环依赖能解决的根本原理就是返回了一个未创建完成的A,
,而且这个A还是一开始创建时候那个半成品的A,简单画个图:

三、继续看populateBean方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
      if (mbd.hasPropertyValues()) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
        return;
      }
    }


    /**给InstantiationAwareBeanPostProcessors最后一次机会
    在属性设置前来改变bean
    */
    boolean continueWithPropertyPopulation = true;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
          InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          //返回值为是否继续填充bean
          if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            continueWithPropertyPopulation = false;
            break;
          }
        }
      }
    }
    //如果后处理器发出停止填充命令则终止后续的执行
    if (!continueWithPropertyPopulation) {
      return;
    }


    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);


    if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      // Add property values based on autowire by name if applicable.
      if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
        //根据名称注入
        autowireByName(beanName, mbd, bw, newPvs);
      }
      // Add property values based on autowire by type if applicable.
      if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
        //根据类型注入
        autowireByType(beanName, mbd, bw, newPvs);
      }
      pvs = newPvs;
    }
    //后处理器已经初始化
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    //需要依赖检查
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);


    if (hasInstAwareBpps || needsDepCheck) {
      if (pvs == null) {
        pvs = mbd.getPropertyValues();
      }
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
          if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            //对所有需要依赖检查的属性进行后处理
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
              return;
            }
          }
        }
      }
      if (needsDepCheck) {
        //依赖检查,对应的depends-on属性
        checkDependencies(beanName, mbd, filteredPds, pvs);
      }
    }
    if (pvs != null) {
      //将属性应用到bean中
      applyPropertyValues(beanName, mbd, bw, pvs);
    }
  }

总结下populateBean中的大概逻辑:

1.InstantiationAwareBeanPostProcessor处理器的

postProcessAfterInstantiation函数的应用,此函数可以控制程序

是否继续进行属性填充。
2.根据注入类型(byName/byType),提取依赖的bean,并统一存入
propertyValues中。
   3.应用InstantiationAwareBeanPostProcessor处理器的
postProcessPropertyValues方法,对属性获取完毕填充前对属性的
再次处理。
   4.将所有PropertyValues中的属性填充至BeanWrapper中。

四、继续看initializeBean方法

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
        invokeAwareMethods(beanName, bean);
        return null;
      }, getAccessControlContext());
    }
    else {
      //对诸如Aware、BeanClassLoaderAware、BeanFactoryAware进行处理
      invokeAwareMethods(beanName, bean);
    }


    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
      //应用后处理器
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }


    try {
      //激活用户自定义的init方法
      invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
      //后处理器应用
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }


    return wrappedBean;
  }

五、注册DisposableBean

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
      if (mbd.isSingleton()) {
        /** 单例模式下注册需要销毁的bean,
        此方法中会处理实现DisposableBean的bean,
        并且对所有的bean使用DestructionAwareBeanPostProcessors处理,
        DisposableBean DestructionAwareBeanPostProcessors
        */
        registerDisposableBean(beanName,
            new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
      }
      else {
        //自定义scope处理
        Scope scope = this.scopes.get(mbd.getScope());
        if (scope == null) {
          throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
        }
        scope.registerDestructionCallback(beanName,
            new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
      }
    }
  }

spring不仅提供了初始化方法的扩展入口,同样也提供了销毁方法的扩展入口,

可以通过配置destroy-method方法实现,也可以注册后处理器

DestructionAwareBeanPostProcessor来统一处理bean的销毁。
    随着这篇文章的结束,spring的bean的加载流程算是写完了,但这只是
冰山一角,每个方法里面调用的方法还可以继续解析,内容实在是太多了,但
是如果你能对bean的加载流程有个大概的了解,主要是那几个关键的方法能说
出来,一般面试的时候有这问题基本上都能答上了!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Yolov5(v5.0) + pyqt5界面设计

1.下载安装pyqt5工具包以及配置ui界面开发环境 pip install PyQt5 pip install PyQt5-tools 2.点击File->Settings->External Tools进行工具添加&#xff0c;依次进行Qt Designer、PyUIC环境配置. 2.1 添加QtDesigner Qt Designer 是通过拖拽的方式放置控件&#xff0c…

GUI编程--PyQt5--QWidget2

文章目录事件事件传递父子关系扩展Z轴的层级关系事件 自定义控件类&#xff08;QWidget&#xff09;&#xff0c;然后重写对应的事件方法即可。 控件显示时触发&#xff0c;showEvent(QShowEvent) 控件关闭时触发&#xff0c;closeEvent(QCloseEvent) 事件传递 案例&#xff1…

MYSQL -- Binlog数据还原

对表误删或执行缺少条件的修改 SQL 导致修改了表内其他数据时&#xff0c;我们需要想办法将数据恢复回来。 先创建两个测试表 table_1 CREATE TABLE table_1 (id int(0) NOT NULL AUTO_INCREMENT,name varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL D…

SpringBoot自定义注解+AOP+redis实现防接口幂等性重复提交,从概念到实战

一、前言 在面试中&#xff0c;经常会有一道经典面试题&#xff0c;那就是&#xff1a;怎么防止接口重复提交&#xff1f; 小编也是背过的&#xff0c;好几种方式&#xff0c;但是一直没有实战过&#xff0c;做多了管理系统&#xff0c;发现这个事情真的没有过多的重视。 最近…

[附源码]java毕业设计酒店管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

K8s为何需要Pod

Pod是K8s中的最小API对象&#xff0c;更专业的表述是&#xff0c;Pod是K8s项目的原子调度单位&#xff0c;Pod可以看做是一个进程组&#xff0c;K8s则是操作系统 一&#xff0c; 问题 现在有三个服务需要部署在同一个节点上&#xff0c;A占用1G内存&#xff0c;B &#xff0c;…

【Maven】使用maven profile 动态激活不同环境、依赖打包部署

使用maven profile 动态激活不同环境、依赖打包部署前言一、配置二、激活Profile三、动态依赖 示例一些其他参考&#xff1a;前言 在开发过程中&#xff0c;我们的软件会面对不同的运行环境&#xff0c;比如开发环境、测试环境、生产环境&#xff0c;而我们的软件在不同的环境中…

Java方法与方法重载

目录 如何使用带参数的方法 综合案例 常见错误2-1 常见错误2-2 方法传参 构造方法 构造方法重载 this的用法 方法重载 成员变量和局部变量 成员变量和局部变量的区别 如何使用带参数的方法 1、定义带参数的方法 语法&#xff1a;<访问修饰符> 返回类型 <方…

网络 IO 演变过程

在互联网中提起网络&#xff0c;我们都会避免不了讨论高并发、百万连接。而此处的百万连接的实现&#xff0c;脱离不了网络 IO 的选择&#xff0c;因此本文作为一篇个人学习的笔记&#xff0c;特此进行记录一下整个网络 IO 的发展演变过程。以及目前广泛使用的网络模型。 1.网…

服务端Skynet(一)——源码浅析

服务端Skynet(一)——源码浅析 文章目录服务端Skynet(一)——源码浅析1、skynet的本质2、skynet基本的数据结构1、skynet_modules管理模块2、skynet_context模块3、skynet_message模块3、skynet启动服务步骤4、启动服务例子(logger)参考文献&#xff1a;skynet设计综述 skynet…

实战Netty!基于私有协议,怎样快速开发网络通信服务?

前言 今天我们一起来来聊聊怎么使用netty。 在工作中&#xff0c;我经常使用netty开发一些服务&#xff0c;掌握netty的工作原理&#xff0c;开发一些服务端以及客户端是非常简单&#xff0c;本篇文章&#xff0c;我们就以具体的协议来进行一个简单的服务的开发。 正文 私有…

一键汇总报告模型可能会需要修改的地方

文章目录如何修改文件夹地址为指定地址?如何取消清除提醒, 避免每次点击弹窗选择?如何取消完成弹窗提醒?如果觉得反复打开工作簿太闪怎么办?如果有些报告的内容页不在第一个Sheet怎么办?如果想修改字段怎么办?运行程序前不想清除原有内容怎么办?报告页有内容但是没有被抓…

混合整数规划的机组组合附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

Redis常见面试题(2022)

Redis基础 什么是 Redis&#xff1f; Redis 是一个开源&#xff08;BSD 许可&#xff09;、基于内存、支持多种数据结构的存储系统&#xff0c;可以作为数据库、缓存和消息中间件。它支持的数据结构有字符串&#xff08;strings&#xff09;、哈希&#xff08;hashes&#xf…

多分类交叉熵理解

多分类交叉熵有多种不同的表示形式&#xff0c;如下图所示&#xff1a; 但是&#xff0c;有时候我们读论文会深陷其中不能自拔。 也有很多读者、观众会纠正其他作者的文章、视频的交叉熵形式。 实际上&#xff0c;上述三种形式都是没有问题的。 这里&#xff0c;我们就要了解…

多媒体内容理解在美图社区的应用实践

导读&#xff1a;移动互联网时代&#xff0c;图像和短视频等多媒体内容爆发&#xff0c;基于计算机视觉的AI算法是多媒体内容分析的基础。在美图社区智能化发展的过程中&#xff0c;视频和图像分类打标、去重以及质量评估的结果&#xff0c;在推荐、搜索以及人工审核等多个场景…

【R语言数据科学】:变量选择(三)主成分回归和偏最小二乘回归

变量选择(三)主成分回归和偏最小二乘回归 🌸个人主页:JOJO数据科学📝个人介绍:统计学top3高校统计学硕士在读💌如果文章对你有帮助,欢迎✌关注、👍点赞、✌收藏、👍订阅专栏✨本文收录于【R语言数据科学】本系列主要介绍R语言在数据科学领域的应用包括: R语言编…

多分类问题的precision和recall以及F1 scores的计算

对于多分类问题&#xff0c;首先&#xff0c;对于每一个类的精准率&#xff08;Precision&#xff09;和召回率&#xff08;Recall&#xff09;&#xff0c;定义和二分类问题一致&#xff0c;但是计算上不再需要TP,FP,FN等量了&#xff1a;&#xff09; 比如对A, B, C三类有如…

SpringBoot中如何集成ThymeLeaf呢?

转自: SpringBoot中如何集成ThymeLeaf呢&#xff1f; 下文笔者将讲述SpringBoot集成ThymeLeaf的方法&#xff0c;如下所示: 实现思路:1.在pom.xml中引入ThymeLeaf的相关依赖2.在Templates文件夹下编写相应的模板文件例: 1.pom.xml 添加ThymeLeaf依赖<!-- ThymeLeaf 依赖…

河南某商务楼BA系统设计

目 录 第一章 概述 3 第二章 设计任务与要求 4 第三章 设计依据和规范 4 第四章 系统设计 5 4.1系统选型 5 4.2 I/O点位设计 7 4.2.1暖通空调系统 11 4.2.2给排水系统 13 4.2.3电气系统 15 4.3线缆选型设计 17 4.4供电接地设计 17 4.5中央控制室设计 18 第五章 设备清单配置 18…