首页 > 编程语言 >Springboot 启动时Bean的创建与注入(二)-面试热点-springboot源码解读-xunznux

Springboot 启动时Bean的创建与注入(二)-面试热点-springboot源码解读-xunznux

时间:2024-07-20 14:55:42浏览次数:14  
标签:Springboot 实例 mbd beanName bean Bean 源码 单例

Springboot 启动时Bean的创建与注入,以及对应的源码解读

文章目录


出于研究springboot启动时bean的创建到注入中发生的函数调用的这个目的,搭建一个最简单的springboot应用,只有一个controller bean,没有再手动指定任何其他bean。获取这个过程的堆栈信息的方法可以看前一篇文章: Springboot 启动时Bean的创建与注入-面试热点-springboot源码解读-xunznux
接下来继续对堆栈中的函数进行简单的解读:

11、getBean:200, AbstractBeanFactory (org.springframework.beans.factory.support)

/**
 * 返回指定Bean的一个实例,该实例可以是共享的也可以是独立的。
 * <p>此方法允许Spring的BeanFactory用作单例模式或原型设计模式的替代品。调用者可以在单例Bean的情况下保留对返回对象的引用。
 * <p>将别名翻译回相应的规范Bean名称。
 * <p>如果在此工厂实例中找不到Bean,将询问父工厂。
 * @param name 要检索的Bean的名称
 * @return Bean的一个实例。
 * 注意,返回值永远不会是{@code null},但可能是工厂方法返回的{@code null}的存根,可以通过{@code equals(null)}进行检查。
 * 考虑使用{@link #getBeanProvider(Class)}来解析可选的依赖项。
 * @throws NoSuchBeanDefinitionException 如果没有具有指定名称的Bean
 * @throws BeansException 如果无法获取Bean
 */

public Object getBean(String name) throws BeansException {
    // beanName = demoApplication
    return this.doGetBean(name, (Class)null, (Object[])null, false);
}

12、doGetBean:335, AbstractBeanFactory (org.springframework.beans.factory.support)

/**
 * 返回指定Bean的一个实例,该实例可以是共享的也可以是独立的。
 * @param name 要检索的Bean的名称
 * @param requiredType 要检索的Bean的所需类型
 * @param args 使用显式参数创建Bean实例时使用的参数
 * (仅在创建新实例时应用,而不是检索现有实例时)
 * @param typeCheckOnly 是否仅为类型检查获取实例,而不是实际使用
 * @return Bean的一个实例
 * @throws BeansException 如果无法创建Bean
 */

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

    // 转换Bean名称,去掉工厂Bean的前缀,将bean名称转换为规范化的名称
    String beanName = transformedBeanName(name);
    Object beanInstance;

    // 立即检查单例缓存中手动注册的单例,尝试从单例缓存中获取bean实例
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
       // 如果存在单例实例且没有传入参数,则直接返回缓存实例
       if (logger.isTraceEnabled()) {
          // 如果bean尚未完全初始化,由于循环引用,记录警告
          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实例对象
       beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
       // 如果正在创建bean实例,则抛出异常,因为可能存在循环引用
       if (isPrototypeCurrentlyInCreation(beanName)) {
          throw new BeanCurrentlyInCreationException(beanName);
       }

       // 检查此工厂中是否存在Bean定义,尝试从父bean工厂获取bean实例
       BeanFactory parentBeanFactory = getParentBeanFactory();
       if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
          // 未找到 -> 检查父工厂,在父工厂中查找bean
          String nameToLookup = originalBeanName(name);
          if (parentBeanFactory instanceof AbstractBeanFactory abf) {
             return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
          }
          else if (args != null) {
             // 使用显式参数委托给父工厂,向父工厂请求带参数的bean
             return (T) parentBeanFactory.getBean(nameToLookup, args);
          }
          else if (requiredType != null) {
             // 没有参数 -> 委托给标准的getBean方法,请求特定类型的bean
             return parentBeanFactory.getBean(nameToLookup, requiredType);
          }
          else {
             return (T) parentBeanFactory.getBean(nameToLookup);
          }
       }

       // 标记bean即将被创建
       if (!typeCheckOnly) {
          // 标记Bean已创建
          markBeanAsCreated(beanName);
       }
       // 启动Bean创建步骤
       StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
             .tag("beanName", name);
       try {
          // 如果指定了所需类型,则记录类型信
          if (requiredType != null) {
             beanCreation.tag("beanType", requiredType::toString);
          }
          // 获取合并后的本地Bean定义
          RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
          // 检查合并后的bean定义
          checkMergedBeanDefinition(mbd, beanName, args);

          // 保证当前Bean依赖的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);
                // 获取依赖的bean
                try {
                   getBean(dep);
                }
                catch (NoSuchBeanDefinitionException ex) {
                   throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                         "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                }
                catch (BeanCreationException ex) {
                   if (requiredType != null) {
                      // 包装异常并附加当前Bean的元数据,但仅在明确请求时(由所需类型指示),不适用于依赖级联
                      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Failed to initialize dependency '" + ex.getBeanName() + "' of " +
                                  requiredType.getSimpleName() + " bean '" + beanName + "': " +
                                  ex.getMessage(), ex);
                   }
                   throw ex;
                }
             }
          }

          // 创建Bean实例
          if (mbd.isSingleton()) {
             sharedInstance = getSingleton(beanName, () -> {
                try {
                   return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                   // 显式从单例缓存中删除实例:它可能已被创建过程急切地放入缓存中(提前暴露),以允许解决循环引用
                   // 还要删除任何接收到该Bean临时引用的Bean
                   destroySingleton(beanName);
                   throw ex;
                }
             });
             beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
          }

          else if (mbd.isPrototype()) {
             // 如果是 prototype(原型模式)  -> 创建一个新实例
             Object prototypeInstance = null;
             try {
                beforePrototypeCreation(beanName);
                prototypeInstance = createBean(beanName, mbd, args);
             }
             finally {
                afterPrototypeCreation(beanName);
             }
             beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
          }

          else {
             // 处理其他作用域的bean
             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) {
          // 记录bean创建失败的信息
          beanCreation.tag("exception", ex.getClass().toString());
          beanCreation.tag("message", String.valueOf(ex.getMessage()));
          cleanupAfterBeanCreationFailure(beanName);
          throw ex;
       }
       finally {
          // 记录bean创建结束
          beanCreation.end();
          // 根据配置决定是否清除bean定义信息
          if (!isCacheBeanMetadata()) {
             clearMergedBeanDefinition(beanName);
          }
       }
    }
    // 适配Bean实例以匹配所需类型
    return adaptBeanInstance(name, beanInstance, requiredType);
}

该doGetBean方法是Spring框架中核心的bean实例化逻辑之一,主要负责根据给定的bean名称、类型和参数来获取或创建一个bean实例。其总体流程和作用可以概括如下:
总体流程

  1. 参数解析与初始化:接收bean的名称、所需的类型、创建实例时可能用到的参数以及是否仅进行类型检查的标志。
  2. 单例缓存检查:首先尝试从单例缓存中获取bean实例,如果存在并且不需要额外参数,则直接返回该实例。
  3. 循环依赖检查:**在创建原型或非单例bean之前,检查是否存在循环引用,防止无限递归。**如果当前正在创建这个 Bean 的实例并且它是原型 Bean,抛出异常以避免循环依赖。
  4. 父级bean工厂代理:如果当前bean工厂中不存在该bean的定义,则尝试递归地从父级bean工厂获取bean实例。
  5. 标记 Bean 为已创建:如果不是仅用于类型检查,将该 Bean 标记为已创建。
  6. 准备 Bean 定义:获取并合并本地的 Bean 定义,检查 Bean 定义的有效性。
  7. 依赖解析与初始化:保所有该 Bean 依赖的 Bean 已经初始化,并检查循环依赖。
  8. 实例创建:根据 Bean 的作用域(单例、原型、其他作用域)创建相应的实例。
    • 单例 Bean:通过单例缓存机制创建并缓存实例。
    • 原型 Bean:每次调用时创建一个新的实例。
    • 其他作用域的 Bean:根据定义的作用域获取实例。
  9. 异常处理与资源清理:捕获并处理bean创建过程中可能出现的各种异常,如循环依赖、未注册的作用域等,同时确保在失败时清理相关资源。
  10. 类型适配与Bean实例返回:返回创建或获取的 Bean 实例,并将其适配为所需的类型。

方法作用:

  • bean实例化的核心:doGetBean方法是Spring IoC容器中bean实例化流程的中心点,它负责整个bean的生命周期管理,包括实例创建、依赖注入、初始化、缓存管理、作用域管理等。通过一系列的步骤确保返回一个有效的 Bean 实例,或者在发生错误时进行适当的清理和异常处理。
  • 灵活的bean获取机制:通过参数控制,可以实现按需创建、类型检查、参数传递等多种获取bean的方式。
  • 错误处理与资源管理:内置了丰富的错误处理机制,能够优雅地处理各种异常情况,并在必要时进行资源的清理和释放。

综上所述,doGetBean方法是Spring框架中极其重要的一部分,它确保了bean的正确创建、管理和使用,是理解和掌握Spring IoC容器工作原理的关键。

13、getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)

单例 Bean 的创建,原型模式以及其他模式的Bean 的创建会在createBean前多调用一个beforePrototypeCreation方法,之后还会调用afterPrototypeCreation方法。
三种方式最后都会调用getObjectForBeanInstance获取实例然后通过adaptBeanInstance返回。

  • beforePrototypeCreation 方法是在原型对象创建之前的回调方法。默认实现将原型对象标记为当前正在创建中,以便跟踪并处理可能的循环依赖。
  • afterPrototypeCreation 方法是在原型对象创建之后的回调方法。它的主要作用是将正在创建的原型对象从创建状态中移除,确保创建过程的正常结束,并清理相关状态。
  • getObjectForBeanInstance 方法用于获取给定 Bean 实例的实际对象。它的作用是处理两种情况:
    • 普通 Bean 实例:直接返回实例。
    • FactoryBean 实例:如果实例是 FactoryBean 类型,则通过 FactoryBean 获取实际的 Bean 对象。
  • adaptBeanInstance 方法用于将一个 Bean 实例转换为所需的类型。它的目标是确保返回的 Bean 实例符合调用者的类型要求,即使原始 Bean 的实际类型可能与所需的类型不完全匹配。如果原始 Bean 的类型与所需类型不匹配,它会尝试进行类型转换。
/**
 * 返回在给定名称下注册的(原始)单例对象,如果没有注册,则创建并注册一个新的单例对象。
 * 
 * @param beanName 要查找的bean的名称
 * @param singletonFactory 用于懒加载创建单例对象的ObjectFactory,在必要时创建单例
 * @return 注册的单例对象
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // 确保bean名称不为空
    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!)");
            }
            
            // 日志记录:正在创建共享的单例bean实例
            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 {
                // 使用提供的ObjectFactory创建单例对象(使用bean工厂创建bean对象)
                singletonObject = singletonFactory.getObject();
                newSingleton = true; // 设置标记,表示创建了新单例
            }
            catch (IllegalStateException ex) {
                // 如果在创建过程中出现IllegalStateException,检查是否是因为单例对象在异常抛出前已被创建
                singletonObject = this.singletonObjects.get(beanName); // (一级缓存)
                if (singletonObject == null) {
                    // 如果单例对象仍然不存在,则重新抛出异常
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                // 如果在创建过程中出现BeanCreationException,记录受抑制的异常
                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;
    }
}

getSingleton方法是Spring框架中DefaultSingletonBeanRegistry类的一部分,用于管理单例bean的创建和访问。该方法的主要功能是在请求时返回一个bean的单例实例,如果该实例尚未创建,则会创建一个新的实例并将其存储在内部的单例集合中。
总体流程

  1. 参数校验:首先,检查传入的beanName参数是否为null,如果是,则抛出IllegalArgumentException。
  2. 同步锁:使用singletonObjects集合的锁来保证线程安全,防止多个线程同时创建同一个bean的实例。
  3. 检查现有实例(一级缓存 singletonObjects):在已有的单例对象集合中查找beanName对应的bean实例。如果找到了,直接返回该实例。
  4. 检查销毁状态:如果缓存中没有找到单例对象,检查是否当前正在销毁单例对象(this.singletonsCurrentlyInDestruction)。如果是,抛出 BeanCreationNotAllowedException。防止在销毁过程中创建新的单例。
  5. 日志记录:如果启用了调试日志,记录创建单例bean的信息。
  6. 调用前置回调:beforeSingletonCreation 方法是一个在单例对象创建之前的回调方法。默认实现将单例对象注册为当前正在创建的对象,以便检测循环依赖。
  7. 异常处理初始化:初始化一个 LinkedHashSet 来记录抑制的异常(this.suppressedExceptions)。
  8. 尝试创建单例对象:
  9. 调用 singletonFactory.getObject() 方法通过 Bean 工厂创建单例对象,并将 newSingleton 标志设为 true。
  10. 捕获 IllegalStateException 异常,如果单例对象已经隐式出现,则继续处理它。
  11. 捕获 BeanCreationException 异常,并记录所有抑制的异常。
  12. 调用后置回调:afterSingletonCreation 方法是在单例对象创建之后的回调方法。默认实现将单例对象标记为不再处于创建状态。
  13. 注册单例对象:如果创建了新的单例对象(newSingleton 为 true),则调用 addSingleton(beanName, singletonObject) 方法将其添加到 singletonObjects 缓存中。
  14. 返回单例实例:返回缓存中或新创建的单例Bean对象。

方法作用:
方法确保了在并发环境下单例对象的安全创建和注册。getSingleton方法的作用在于确保每个bean的单例实例在整个应用上下文中唯一,并且在首次请求时创建,后续请求直接返回已创建的实例。这种方法有效地减少了资源消耗,提高了应用的响应速度。同时,通过同步机制和异常处理,保证了单例bean的创建过程线程安全且健壮,即使在复杂的并发场景下也能正常工作。
总之,getSingleton方法是Spring框架中单例bean管理的核心,它不仅实现了单例模式的基本功能,还提供了异常处理、线程安全和生命周期管理的高级特性,是Spring IoC容器高效运行的基础。

14、getObject:-1, AbstractBeanFactory$$Lambda$330/0x0000020b811ebab8 (org.springframework.beans.factory.support)

/**
 * 定义了一个工厂,该工厂在调用时可以返回一个对象实例
 * (可能是共享的或独立的)。
 *
 * <p>此接口通常用于封装一个通用工厂,该工厂在每次调用时返回一个新的实例(原型)。
 *
 * <p>该接口类似于 {@link FactoryBean},但后者的实现通常作为 SPI 实例在
 * {@link BeanFactory} 中定义,而本接口的实现通常作为 API 提供给其他 Bean(通过注入)。
 * 因此,{@code getObject()} 方法具有不同的异常处理行为。
 *
 * @author Colin Sampaleanu
 * @since 1.0.2
 * @param <T> 对象类型
 * @see FactoryBean
 */
@FunctionalInterface
public interface ObjectFactory<T> {

    /**
     * 返回由此工厂管理的对象的实例(可能是共享的或独立的)。
     * @return 结果实例
     * @throws BeansException 如果创建过程出现错误
     */
    T getObject() throws BeansException;

}

ObjectFactory 接口提供了一种机制来获取由工厂管理的对象实例。getObject() 返回由工厂管理的对象实例。这个实例可以是共享的(即所有调用者共享同一个实例)或者是独立的(即每次调用都返回一个新的实例)。

15、lambda$doGetBean$0:337, AbstractBeanFactory (org.springframework.beans.factory.support)

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

这是doGetBean方法中通过lambda调用createBean的代码片段。

16、createBean:522, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)

/**
 * 此类的核心方法:创建bean实例,填充bean实例,应用后处理器等。
 * 
 * @param beanName bean的名称
 * @param mbd      根bean定义
 * @param args     构造函数参数
 * @return 创建的bean实例
 * @throws BeanCreationException 如果在bean创建过程中发生错误
 * 
 * @see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
       throws BeanCreationException {

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

    // 确保在此时已经实际解析了bean类,并在动态解析的Class情况下克隆bean定义,
    // 这样的Class不能存储在共享的合并bean定义中。
    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 {
       // 给BeanPostProcessors一个机会,返回代理而不是目标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.isTraceEnabled()) {
          logger.trace("Finished creating instance of bean '" + beanName + "'");
       }
       return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
       // 已经检测到带有适当bean创建上下文的异常,或者非法的单例状态将向上通信至DefaultSingletonBeanRegistry。
       throw ex;
    }
    catch (Throwable ex) {
       throw new BeanCreationException(
             mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

createBean方法是Spring框架中负责bean实例创建的核心方法,其主要流程如下:

  1. 日志记录:首先,如果日志级别为TRACE,记录开始创建 Bean 的日志信息。
  2. 解析和克隆 Bean 定义:确保bean的类已经被解析,并根据需要克隆bean定义。如果bean类是在运行时动态解析的,那么克隆 Bean 定义,创建一个新的RootBeanDefinition实例,并设置解析后的类。方法prepareMethodOverrides 主要用于验证和准备为 Bean 定义的方法覆盖。它的作用是检查和处理 Bean 定义中声明的方法覆盖(method overrides),确保这些覆盖方法在目标 Bean 中有效,并且遵循一定的规则。
  3. 预实例化处理:调用resolveBeforeInstantiation方法,检查BeanPostProcessor是否可以在实例化之前返回一个代理对象(如 AOP 代理)而非实际的bean实例。如果返回非空对象,直接返回这个对象,不再进行后续的bean实例创建。
    • resolveBeforeInstantiation 方法用于在实例化 Bean 之前,应用一些处理逻辑,这些处理逻辑可能会导致直接返回一个现成的 Bean 实例,而不是创建新的实例。这通常用于处理 Bean 的提前处理和优化,尤其是在使用了 BeanPostProcessor 的情况下。
  4. 实际创建bean实例:如果预实例化阶段没有返回对象,调用doCreateBean方法,这是实际创建bean实例的地方,包括初始化、属性注入、后处理器应用等。
  5. 异常处理:整个bean创建过程中,对可能出现的各种异常进行捕获和重新抛出,确保异常信息的完整性和上下文的准确性。
  6. 日志记录:如果bean创建成功,且日志级别为TRACE,记录一条消息,表示完成了bean实例的创建。

通过上述步骤,createBean方法不仅创建了bean实例,还确保了bean的生命周期管理、依赖注入以及各种后处理器的正确应用,是Spring框架中bean管理的核心组件之一。
createBean方法是Spring框架中BeanFactory的核心实现之一,位于AbstractAutowireCapableBeanFactory类中,用于完成bean的实例化、配置和初始化的全过程。它是Spring IoC容器中bean生命周期管理的基石,确保了bean能够按照预定的规则正确创建和初始化。

17、doCreateBean:599, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)

/**
 * 实际创建指定的bean。在此之前,已进行了预创建处理,例如检查{@code postProcessBeforeInstantiation}回调。
 * <p>区分默认的bean实例化、使用工厂方法和自动装配构造器。
 *
 * @param beanName bean的名称
 * @param mbd 合并后的bean定义
 * @param args 构造函数或工厂方法调用时使用的显式参数
 * @return bean的新实例
 * @throws BeanCreationException 如果无法创建bean
 * @see #instantiateBean
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 */
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
       throws BeanCreationException {

    // 实例化bean。
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
       // 从缓存中尝试获取单例bean的实例包装器,以支持原型作用域内的单例工厂bean。
       instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
       // 如果没有从缓存中获取到,调用方法创建新的bean实例。
       instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
       // 记录解析后的目标类型,用于后续依赖查找。
       mbd.resolvedTargetType = beanType;
    }

    // 允许后处理器修改合并的bean定义。
    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);
          }
          // 标记bean定义已完成后处理。
          mbd.markAsPostProcessed();
       }
    }

    // 对于单例bean,且允许循环引用的情况下,提前暴露bean,以便解决潜在的循环引用问题。
    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");
       }
       // 添加一个单例工厂,用于提前获取bean的引用。
       addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // 初始化bean实例。
    Object exposedObject = bean;
    try {
       // 填充bean属性。
       populateBean(beanName, mbd, instanceWrapper);
       // 执行初始化方法,获取最终的bean实例。
       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);
       }
    }
    
    // 如果提前暴露了单例,则进行相应的处理,以确保依赖的bean使用正确的bean实例。
    if (earlySingletonExposure) {
       // 获取最终的单例引用。
       Object earlySingletonReference = getSingleton(beanName, false);
       if (earlySingletonReference != null) {
          // 如果当前bean就是最终的bean,则直接使用提前暴露的引用。
          if (exposedObject == bean) {
             exposedObject = earlySingletonReference;
          }
          // 检查是否有依赖于原始bean的其他bean,确保它们能使用最终版本的bean。
          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.");
             }
          }
       }
    }

    // 注册bean的销毁方法,以便在容器关闭时执行。
    try {
       registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
       throw new BeanCreationException(
             mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    
    // 返回最终的bean实例。
    return exposedObject;
}
  1. 实例化 Bean:实际创建 Bean 实例。检查 Bean 是否是单例,是否需要缓存,是否使用工厂方法。通过 createBeanInstance 方法创建 Bean 实例,可能使用构造函数或工厂方法。
  2. 设置 Bean 类型:设置 RootBeanDefinition 对象的 resolvedTargetType 属性为新创建的 Bean 类型。
  3. 应用 Bean 后处理器:在 Bean 实例化后允许对 Bean 定义进行进一步处理。这包括配置、修正或增强 Bean 实例。在 synchronized 块中,如果 Bean 定义尚未被后置处理器处理过,就调用 applyMergedBeanDefinitionPostProcessors 方法来允许 BeanPostProcessors 修改合并后的 Bean 定义。使用 applyMergedBeanDefinitionPostProcessors 方法应用所有定义的后处理器。
  4. 缓存单例 Bean与处理循环引用:解决 Bean 循环依赖问题。通过提前缓存单例 Bean,确保可以在 Bean 初始化过程中解决依赖问题。如果 Bean 是单例并且允许循环引用,则调用 addSingletonFactory 方法缓存早期 Bean 引用。
  5. 初始化 Bean:填充 Bean 属性(如依赖注入)并调用初始化方法。 使用 populateBean 方法填充 Bean,调用 initializeBean 方法进行初始化(如调用 init 方法、应用后处理器等)。
  6. 处理早期单例引用:确保循环引用问题得到解决,即使在 Bean 初始化过程中可能存在的早期暴露问题。如果 Bean 是单例并且已经提前缓存,则处理早期暴露的情况,确保其他依赖 Bean 获取到最终的 Bean 实例。
  7. 注册销毁方法:确保 Bean 在容器关闭时能够正确执行销毁逻辑。调用 registerDisposableBeanIfNecessary 方法注册销毁方法,以处理 Bean 的销毁逻辑。
  8. 返回 Bean 实例: 返回经过初始化和可能的包装后的 Bean 实例。

doCreateBean 方法负责从创建到初始化整个 Bean 的过程,确保 Bean 实例在容器中被正确创建、配置、初始化和销毁。它处理了 Bean 的实例化、后处理、循环依赖、早期暴露、属性填充、初始化和销毁等多个方面的逻辑。

/**
 * 获取对指定 Bean 的早期访问引用,
 * 通常用于解决循环依赖问题。
 * @param beanName Bean 的名称(用于错误处理)
 * @param mbd Bean 的合并 Bean 定义
 * @param bean 原始 Bean 实例
 * @return 作为 Bean 引用暴露的对象
 */
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    // 初始化暴露的对象
    Object exposedObject = bean;
    // 检查是否需要处理早期 Bean 引用
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        // 应用早期 Bean 引用处理器:遍历所有,这些处理器能够在 Bean 实例化的早期阶段进行特定的处理。
       for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
          exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
       }
    }
    // 返回处理后的 Bean 引用:可能是原始 Bean 实例,也可能是经过处理器转换后的 Bean 实例。
    return exposedObject;
}

getEarlyBeanReference 方法的主要作用是在 Bean 实例化的早期阶段,通过调用 SmartInstantiationAwareBeanPostProcessor 的 getEarlyBeanReference 方法来获取 Bean 的引用。这通常用于解决 Bean 的循环依赖问题,在 Bean 实例化过程中,可能需要提前暴露 Bean 的引用,以便其他 Bean 可以依赖它。这个方法确保了即使在 Bean 实例化过程中遇到循环依赖的情况,也能够正确地处理并提供 Bean 的引用。

18、createBeanInstance:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

/**
 * 为指定的 bean 创建一个新实例,使用合适的实例化策略:
 * 工厂方法、构造函数自动装配或简单实例化。
 * @param beanName bean 的名称
 * @param mbd bean 的定义
 * @param args 构造函数或工厂方法调用的显式参数
 * @return 新实例的 BeanWrapper
 * @see #obtainFromSupplier
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 * @see #instantiateBean
 */
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 确保此时 bean 类已解析。
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    // 如果 bean 类存在且不是公共的,并且不允许非公共访问,则抛出异常。
    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());
    }

    // 如果没有参数,尝试使用实例提供者获取实例。
    if (args == null) {
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName, mbd);
        }
    }

    // 如果定义了工厂方法,使用工厂方法实例化。
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // 重新创建相同 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);
        }
    }

    // 通过bean后处理器确定构造器用于自动装配。
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // 尝试使用首选构造器进行默认构造。
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // 没有特殊处理:仅使用无参构造函数。
    return instantiateBean(beanName, mbd);
}

该函数 createBeanInstance 的主要作用是为指定的 bean 创建一个新实例,使用合适的实例化策略,如工厂方法、构造函数自动装配或简单实例化。其总体流程和作用如下:

  1. 解析 Bean 类

    • 确保在此时已解析 bean 类。调用 resolveBeanClass 方法获取 bean 类。
  2. 检查 Bean 类的访问修饰符

    • 如果 bean 类存在且不是公共的,并且不允许非公共访问,则抛出 BeanCreationException 异常。
  3. 尝试使用实例提供者创建实例

    • 如果没有提供构造函数参数 args,则尝试从 bean 定义中获取实例提供者 instanceSupplier 并使用它创建实例。
  4. 使用工厂方法实例化

    • 如果 bean 定义中指定了工厂方法名称,则使用工厂方法进行实例化。
  5. 重新创建相同 Bean 的快捷方式

    • 检查是否已经解析了构造函数或工厂方法,如果是,则根据之前的解析结果进行实例化。
  6. 自动装配构造函数

    • 如果存在自动装配的候选构造函数,或者需要自动装配构造函数,或者有构造函数参数值,则进行构造函数的自动装配。
  7. 首选构造函数

    • 如果定义了首选构造函数,则使用这些构造函数进行自动装配。
  8. 默认实例化

    • 如果没有特殊处理,则使用无参构造函数进行简单实例化。

通过这些步骤,函数灵活地处理不同的实例化需求,确保正确地创建 bean 实例。

19、populateBean:1421, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)

/**
 * 用 bean 定义中的属性值填充给定 BeanWrapper 中的 bean 实例。
 * @param beanName bean 的名称
 * @param mbd bean 的定义
 * @param bw 包含 bean 实例的 BeanWrapper
 */
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 如果 BeanWrapper 为 null,且 bean 定义中有属性值,则抛出异常
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // 如果BeanWrapper为null且无属性值,跳过属性填充阶段。
            return;
        }
    }

    // 如果Bean的类是一个记录(record),检查是否存在属性值,如果有则抛出异常,因为记录是不可变的。
    if (bw.getWrappedClass().isRecord()) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");
        }
        else {
            // 对于 record 类型实例(不可变),跳过属性填充阶段
            return;
        }
    }

    // 给 InstantiationAwareBeanPostProcessors 机会修改 bean 状态
    // 在设置属性之前,这可以用于支持字段注入等风格
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // 如果后处理器的 postProcessAfterInstantiation 方法返回 false,跳过属性填充
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }

    // 获取 bean 定义中的属性值(如果有的话)
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // 获取 bean 定义中解析后的自动装配模式
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    // 如果自动装配模式是按名称或按类型,则创建新的属性值对象
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // 根据按名称自动装配模式添加属性值(如果适用)
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // 根据按类型自动装配模式添加属性值(如果适用)
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }
    // 如果存在 InstantiationAwareBeanPostProcessors,处理属性值
    if (hasInstantiationAwareBeanPostProcessors()) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // 使用后处理器的 postProcessProperties 方法处理属性值
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            // 如果返回的属性值为 null,跳过后续处理
            if (pvsToUse == null) {
                return;
            }
            pvs = pvsToUse;
        }
    }

    // 检查 bean 定义中的依赖项是否需要检查
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    if (needsDepCheck) {
        // 过滤属性描述符以用于依赖检查
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        // 检查属性依赖
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    // 应用属性值到 bean 实例(如果存在属性值)
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}
  1. 检查 BeanWrapper 是否为 null:
    • 如果 BeanWrapper 为 null,且 bean 定义中有属性值,则抛出异常。
    • 如果 bean 定义中没有属性值,则跳过属性填充阶段。
  2. 检查 bean 实例是否是 record 类型:
    • 如果 bean 实例是 record 类型且 bean 定义中有属性值,则抛出异常。
    • 如果 bean 实例是 record 类型且没有属性值,则跳过属性填充阶段,因为 record 类型是不可变的。
  3. 处理 InstantiationAwareBeanPostProcessors:
    • 如果 bean 定义不是合成的并且存在 InstantiationAwareBeanPostProcessors,则调用这些后处理器的 postProcessAfterInstantiation 方法来允许修改 bean 实例的状态。
    • 如果任何后处理器的 postProcessAfterInstantiation 方法返回 false,则跳过属性填充。
  4. 获取并处理属性值
    • 从 bean 定义中获取属性值(如果有)。
    • 根据 bean 定义中的自动装配模式(按名称或按类型),创建并修改属性值集合。
      • 按名称自动装配:添加相应的属性值。
      • 按类型自动装配:添加相应的属性值。
  5. 再次处理 InstantiationAwareBeanPostProcessors:
    • 如果存在 InstantiationAwareBeanPostProcessors,使用这些后处理器的 postProcessProperties 方法进一步处理属性值。
  6. 依赖项检查:
    • 根据 bean 定义中的依赖检查设置,过滤属性描述符,并检查 bean 的属性依赖。
  7. 应用属性值:
    • 将最终的属性值应用到 bean 实例中。

作用:

  • 属性填充:populateBean 方法的主要作用是将从 bean 定义中提取的属性值应用到 bean 实例中。这包括处理自动装配、后处理器的干预、以及依赖项的检查。
  • 灵活性:通过处理 InstantiationAwareBeanPostProcessors,该方法允许在属性设置之前或之后对 bean 进行额外的定制和修改。
  • 保证一致性:在依赖项检查中确保 bean 实例的完整性和一致性,避免由于属性设置错误导致的运行时错误。

20、postProcessProperties:508, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)

/**
 * 在工厂将属性值应用于给定的 bean 之前对其进行后处理。
 * <p>默认实现返回传入的 {@code pvs}。
 * @param pvs 工厂即将应用的属性值(从不为 {@code null})
 * @param bean 已创建但属性尚未设置的 bean 实例
 * @param beanName bean 的名称
 * @return 实际要应用于给定 bean 的属性值(可以是传入的 PropertyValues 实例),或 {@code null} 以跳过属性填充
 * @throws org.springframework.beans.BeansException 在出现错误的情况下
 * @since 5.1
 */
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 查找和 bean 相关的资源元数据
    InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    try {
        // 注入元数据中的资源依赖
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        // 捕捉注入过程中出现的任何错误,并抛出 BeanCreationException 异常
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    // 返回处理后的属性值(默认是传入的 pvs)
    return pvs;
}

函数注释和总体流程总结

该函数 postProcessProperties 的作用是对给定的属性值进行后处理,然后工厂将这些属性应用于给定的 bean。它可以修改属性值,或者决定跳过属性填充。默认实现返回传入的 pvs。具体流程如下:

/**
 * 在工厂将属性值应用于给定的 bean 之前对其进行后处理。
 * <p>默认实现返回传入的 {@code pvs}。
 * @param pvs 工厂即将应用的属性值(从不为 {@code null})
 * @param bean 已创建但属性尚未设置的 bean 实例
 * @param beanName bean 的名称
 * @return 实际要应用于给定 bean 的属性值(可以是传入的 PropertyValues 实例),或 {@code null} 以跳过属性填充
 * @throws org.springframework.beans.BeansException 在出现错误的情况下
 * @since 5.1
 */
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 查找和 bean 相关的资源元数据
    InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    try {
        // 注入元数据中的资源依赖
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        // 捕捉注入过程中出现的任何错误,并抛出 BeanCreationException 异常
        throw new BeanCreationException(beanName, "注入资源依赖失败", ex);
    }
    // 返回处理后的属性值(默认是传入的 pvs)
    return pvs;
}
  1. 查找资源元数据

    • 调用 findResourceMetadata 方法,传入 beanNamebean 的类和属性值 pvs
    • findResourceMetadata 方法的作用是查找和当前 bean 相关的资源元数据。
  2. 注入元数据中的资源依赖

    • 调用 metadata.inject(bean, beanName, pvs) 方法,将查找到的元数据中的资源依赖注入到 bean 实例中。
    • 如果注入过程中出现任何错误,会捕捉到并抛出 BeanCreationException 异常,说明资源依赖注入失败。
  3. 返回属性值

    • 返回处理后的属性值 pvs,默认实现是返回传入的 pvs,即没有修改。

该方法在 bean 实例的属性填充之前,对属性值进行后处理,主要是通过元数据注入资源依赖。这确保了 bean 实例在属性设置之前完成了所需的依赖注入。如果注入失败,会抛出异常,终止 bean 的创建过程。

21、inject:142, InjectionMetadata (org.springframework.beans.factory.annotation)

/**
 * 对目标对象进行依赖注入。
 * 
 * 此方法负责遍历一组注入元素,并对每个元素调用其inject方法,以注入依赖到目标对象中。
 * 它支持两种不同的注入元素集合:已检查的元素和所有的注入元素。已检查的元素可能是一个子集,
 * 用于特定条件或场景下的依赖注入。
 * 
 * @param target 需要进行依赖注入的目标对象。
 * @param beanName 目标对象的bean名称,可能为null。
 * @param pvs 目标对象的属性值,可能为null。
 * @throws Throwable 如果注入过程中发生任何异常,将抛出异常。
 */
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	// 获取已检查的注入元素集合,如果为空则使用所有的注入元素集合。
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
	
	// 如果存在注入元素,遍历并逐一进行依赖注入。
	if (!elementsToIterate.isEmpty()) {
		for (InjectedElement element : elementsToIterate) {
			element.inject(target, beanName, pvs);
		}
	}
}

该方法的作用是对目标对象 target 进行依赖注入。它会检查是否有已经验证过的注入元素集合,如果有则使用它,否则使用原始的注入元素集合。然后,它会迭代这些注入元素,并对每个元素进行依赖注入。这样确保了目标对象在创建或初始化过程中,能够正确地注入所需的依赖。

22、讲讲三级缓存的使用

// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
/**
 * 返回在给定名称下注册的(原始)单例对象。
 * <p>
 * 检查已实例化的单例对象,并允许引用当前正在创建的单例(解决循环引用问题)。
 * 
 * @param beanName 要查找的bean的名称
 * @param allowEarlyReference 是否允许创建早期引用
 * @return 注册的单例对象,如果没有找到则返回{@code null}
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
     // 快速检查已存在的实例,避免完全锁定单例
    Object singletonObject = this.singletonObjects.get(beanName);
    
    // 如果未找到实例,但是当前有单例正在创建中
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        // 尝试从早期单例对象中获取
        singletonObject = this.earlySingletonObjects.get(beanName);
        // 如果允许早期引用并且还未找到实例
        if (singletonObject == null && allowEarlyReference) {
            synchronized(this.singletonObjects) {
            // 在完全锁定单例的情况下,一致地创建早期引用
                 
                 // 再次检查,以防在上锁前有其他线程已经创建了单例
                singletonObject = this.singletonObjects.get(beanName);// 一级缓存
                if (singletonObject == null) {
                    // 再次尝试从早期单例对象中获取
                    singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
                    if (singletonObject == null) {
                        // beanName = viewResolver时会进来
                        // 三级缓存
                         // 从单例工厂中获取ObjectFactory,用于创建单例
                        ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                        
                        // 如果找到了对应的工厂
                        if (singletonFactory != null) {
                            // Bean 工厂创建单例对象 使用工厂创建单例对象
                            singletonObject = singletonFactory.getObject();
                            // Bean 加入二级缓存,将创建的单例对象存储到早期单例对象Map中
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            // 删除三级缓存Bean对象,移除单例工厂条目,因为单例已经创建完成
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    // 返回找到的单例对象,或者null
    return singletonObject;
}

整体流程

  1. 快速检查:首先,方法会尝试从singletonObjects Map中快速查找是否存在已经创建好的单例bean。这是最直接和高效的获取方式。
  2. 检测创建状态:如果singletonObjects中未找到bean,但isSingletonCurrentlyInCreation返回true,这意味着当前有线程正在创建该bean。此时,方法会进一步检查earlySingletonObjects Map,看是否已经有线程提前创建了bean的早期引用。
  3. 早期引用创建:如果allowEarlyReference为true,且earlySingletonObjects中也未找到bean,那么方法会在synchronized块内,使用singletonFactories中的ObjectFactory来创建bean的早期引用。这一步骤解决了循环依赖的问题,即当两个bean相互依赖时,可以通过早期引用先满足依赖关系,待创建完成后,再替换为完整的bean实例。
  4. 线程安全处理:在创建早期引用的过程中,使用synchronized关键字确保了线程安全,防止多个线程同时创建同一bean的早期引用。
  5. 清理与更新:一旦bean的早期引用创建完成,会将其存入earlySingletonObjects Map,并从singletonFactories中移除对应的条目,表明该bean已经处于创建状态。
  6. 返回结果:最后,方法返回找到的bean实例,可能是从singletonObjects中直接获取的成熟bean,也可能是从earlySingletonObjects中获取的早期引用。

方法作用:

  • 确保单例模式:getSingleton方法的核心作用是确保bean的单例模式,即在整个应用上下文中,每个bean的实例只存在一份,多次请求同一bean将返回相同的实例。
  • 处理循环依赖:通过引入早期引用的概念,getSingleton能够优雅地处理循环依赖问题,使得依赖关系可以在bean创建的初期就得以满足,避免了因循环依赖而导致的死锁或异常。
  • 线程安全:在多线程环境中,getSingleton方法通过适当的锁机制,保证了bean创建和获取过程的线程安全,避免了并发问题。
    综上所述,getSingleton方法是Spring框架中bean生命周期管理的关键部分,它通过一系列精心设计的步骤,确保了bean的单例模式得以正确实施,同时也处理了复杂的依赖关系和并发问题,是Spring框架高效稳定运行的重要保障。

其他内容

如果对 Golang 实现的Raft共识算法、Golang实现的负载均衡或者 Golang web 项目的demo实现感兴趣的可以看看我的主页,各个部分都带有详细的代码解释,也可以通过代码仓库获取源码,直接运行。

Golang相关内容的gitee链接

标签:Springboot,实例,mbd,beanName,bean,Bean,源码,单例
From: https://blog.csdn.net/weixin_44615954/article/details/140560807

相关文章

  • php在线客服系统|客服系统源码(开源代码+安装教程)
    在线客服系统源码与您的日常客户沟通渠道连接,包括电子邮件、电话、实时聊天、社交媒体集成、消息应用程序,甚至客户服务门户。当客户通过任何这些渠道联系您的企业时,系统会自动创建票证。例如,如果客户使用实时渠道(例如电话或实时聊天),系统会自动开始响铃以提醒在线支持......
  • Java计算机毕业设计秒杀系统实现(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展和电子商务的蓬勃兴起,秒杀活动作为一种高效促销手段,在各大电商平台中屡见不鲜。秒杀活动以其时间紧迫、价格诱人的特点,迅速......
  • Java计算机毕业设计老年教育学习系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着全球人口老龄化的加速,老年教育作为提升老年人生活质量、促进终身学习的重要途径,日益受到社会各界的关注。然而,传统教育模式在满足老年人多样化、......
  • SpringBoot+Vue的闲一品零食交易平台(前后端分离)
    技术栈JavaSpringBootMavenMySQLmybatisVueShiroElement-UI角色对应功能网站用户管理员项目功能截图......
  • SpringBoot+Vue的进存销管理系统(前后端分离)
    技术栈JavaSpringBootMavenMySQLmybatisVueShiroElement-UI角色对应功能管理员员工项目功能截图......
  • 基于Java Springboot餐厅点餐系统
    作者介绍:✌全网粉丝10W+本平台特邀作者、博客专家、CSDN新星计划导师、软件领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于项目实战✌一、作品包含源码+数据库+设计文档万字+全套环境和工具资源+部署教程二、项目技术前端技术:Html、Css......
  • 基于Java Springboot宠物管理系统
    作者介绍:✌全网粉丝10W+本平台特邀作者、博客专家、CSDN新星计划导师、软件领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于项目实战✌一、作品包含源码+数据库+设计文档万字+全套环境和工具资源+部署教程二、项目技术前端技术:Html、Css......
  • 毕设项目:springboot+vue实现的在线求职平台
    一、前言    随着信息技术的飞速发展和互联网的普及,线上求职已成为众多求职者和企业招聘的重要渠道。为满足市场需求,我们利用SpringBoot和Vue技术栈,开发了一款功能全面、用户友好的在线求职平台。本文将对该平台的设计、实现及关键技术进行详细介绍。本文介绍基于spring......
  • Chromium源码阅读(8):了解Base库里的PartitionAlloc模块
    Chromium代码库不是只使用malloc()。例如:渲染器(Blink)的大部分使用两个自制的分配器,PartitionAlloc和BlinkGC(Oilpan)。一些子系统(例如V8JavaScript引擎)可以自主处理内存管理。代码库的各个部分使用诸如SharedMemory或DiscardableMemory之类的抽象,与上述类似,它们有自己......
  • SSM城镇居民社区再生资源回收系统-计算机毕业设计源码04175
    摘 要本论文介绍了一个基于SSM(Spring+SpringMVC+MyBatis)技术的城镇居民社区再生资源回收系统的设计与实现。随着社会对环境保护意识的不断提高,再生资源回收成为了一种重要的环保行动。然而,传统的再生资源回收方式存在着信息不对称、流程繁琐等问题,导致回收效率低下。......