Spring IOC源码:finishBeanFactoryInitialization详解

简介: Spring IOC源码:finishBeanFactoryInitialization详解

文章目录

Spring源码系列:

前言

正文

方法1:preInstantiateSingletons

方法2:getMergedLocalBeanDefinition

方法3:getMergedBeanDefinition

方法4:transformedBeanName

方法5:isFactoryBean

方法6:getSingleton

方法7:isFactoryBean

总结

Spring源码系列:

Spring IOC源码:简单易懂的Spring IOC 思路介绍

Spring IOC源码:核心流程介绍

Spring IOC源码:ApplicationContext刷新前准备工作

Spring IOC源码:obtainFreshBeanFactory 详解(上)

Spring IOC源码:obtainFreshBeanFactory 详解(中)

Spring IOC源码:obtainFreshBeanFactory 详解(下)

Spring IOC源码:<context:component-scan>源码详解

Spring IOC源码:invokeBeanFactoryPostProcessors 后置处理器详解

Spring IOC源码:registerBeanPostProcessors 详解

Spring IOC源码:实例化前的准备工作

Spring IOC源码:finishBeanFactoryInitialization详解

Spring IoC源码:getBean 详解

Spring IoC源码:createBean( 上)

Spring IoC源码:createBean( 中)

Spring IoC源码:createBean( 下)

Spring IoC源码:finishRefresh 完成刷新详解

前言

这篇文章开始讲解Bean的实例化过程,也就是refresh中的finishBeanFactoryInitialization方法,该方法是IOC中最核心也是最复杂的,后续会分为几篇文章进行详细讲解。该方法会将beanFactory工厂中的定义信息进行实例化及属性注入;

正文

进入fresh中的finishBeanFactoryInitialization方法

  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 判断beanFactory工厂中是否有ConversionService或其定义信息,没有则实例化创建一个ConversionService转换器
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
        beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
          beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    //如果工厂中没有嵌入式解析器,则创建一个默认的
    if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    //实例化LoadTimeWeaverAware对象
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
    }
    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);
    // Allow for caching all bean definition metadata, not expecting further changes.
    //冻结bean定义信息,不允许bean定义信息被修改,因为要开始实例化了
    beanFactory.freezeConfiguration();
    // 实例化剩余的懒加载的bean
    beanFactory.preInstantiateSingletons();
  }

beanFactory.preInstantiateSingletons(),见方法1详解

方法1:preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
    }
    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    //复杂一份新的beanName用于遍历,因为bean中的init方法可能会创建新的bean定义信息
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // Trigger initialization of all non-lazy singleton beans...
    //遍历所有非懒加载beanName
    for (String beanName : beanNames) {
      //该bean可能存在父类定义,这里合并后封装成RootBeanDefinition 对象,后续操作都是使用RootBeanDefinition 
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //不是抽象、且非懒加载的单例
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        //判断是否的factoryBean
        if (isFactoryBean(beanName)) {
          //获取factoryBean本对象,这里如果beanName带&前缀的话获取的是FactoryBean对象,如果是不带前缀的beanName,则获取的是FactoryBean中的getObject返回的实例。
          Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
          if (bean instanceof FactoryBean) {
            final FactoryBean<?> factory = (FactoryBean<?>) bean;
            //用于标识是否是急切初始化
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
              isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                      ((SmartFactoryBean<?>) factory)::isEagerInit,
                  getAccessControlContext());
            }
            else {
            //如果实现了SmartFactoryBean 接口,则该Bean会提前进行创建
              isEagerInit = (factory instanceof SmartFactoryBean &&
                  ((SmartFactoryBean<?>) factory).isEagerInit());
            }
            //如果是急切初始化,提前进行生成
            if (isEagerInit) {
              getBean(beanName);
            }
          }
        }
        else {
        //非FactoryBean,直接实例化Bean
          getBean(beanName);
        }
      }
    }
    // Trigger post-initialization callback for all applicable beans...
    //遍历所有的Bean,如果为SmartInitializingSingleton类型,则调用其afterSingletonsInstantiated方法。
    for (String beanName : beanNames) {
    //从一级缓存中获取对象
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            smartSingleton.afterSingletonsInstantiated();
            return null;
          }, getAccessControlContext());
        }
        else {
          smartSingleton.afterSingletonsInstantiated();
        }
      }
    }
  }

假如该工厂bean的beanName为myFactoryBean,当我们传入myFactoryBean去获取Bean的时候返回的其实是Student对象,如果传入的是带前缀的&myFactoryBean,则返回的是MyFactoryBean 本身这个实例。


2、在整个IOC中我们经常会看到getBean(beanName)方法,其参数是一个beanName。该方法是将beanFactory工厂中的定义信息进行实例化的节点,传入beanName,会先从缓存中查询是否存在,存在则返回,不存在则会进行创建。


getMergedLocalBeanDefinition(beanName),见方法2详解

isFactoryBean(beanName),见方法5详解

方法2:getMergedLocalBeanDefinition

  protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    // 从缓存中查询是否存在该定义信息
    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    if (mbd != null && !mbd.stale) {
      return mbd;
    }
    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
  }
  protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
      throws BeanDefinitionStoreException {
    return getMergedBeanDefinition(beanName, bd, null);
  }

getMergedBeanDefinition(beanName, bd, null),见方法3详解

方法3:getMergedBeanDefinition

protected RootBeanDefinition getMergedBeanDefinition(
      String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
      throws BeanDefinitionStoreException {
    synchronized (this.mergedBeanDefinitions) {
      RootBeanDefinition mbd = null;
      RootBeanDefinition previous = null;
      // Check with full lock now in order to enforce the same merged instance.
      if (containingBd == null) {
      //尝试从缓存中获取
        mbd = this.mergedBeanDefinitions.get(beanName);
      }
      if (mbd == null || mbd.stale) {
        previous = mbd;
        mbd = null;
        //判断该bean是否存在父类,如果没有则判断本身是否是RootBeanDefinition,否则创建一个新的RootBeanDefinition
        if (bd.getParentName() == null) {
          // Use copy of given root bean definition.
          //一般BeanDefinition在被加载后是GenericBeanDefinition或ScannedGenericBeanDefinition
          if (bd instanceof RootBeanDefinition) {
            mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
          }
          else {
            mbd = new RootBeanDefinition(bd);
          }
        }
        else {
          // Child bean definition: needs to be merged with parent.
          BeanDefinition pbd;
          try {
            //获取父类名称
            String parentBeanName = transformedBeanName(bd.getParentName());
            //如果父类与当前beanName不一致,则递归调用当前方法进行查找合并,因为父类也有可能存在父类。。
            if (!beanName.equals(parentBeanName)) {
              pbd = getMergedBeanDefinition(parentBeanName);
            }
            else {
              //获取父类的BeanFactory 
              BeanFactory parent = getParentBeanFactory();
              //只有在存在父BeanFactory的情况下,才允许父定义beanName与自己相同,否则就是将自己设置为父定义
              if (parent instanceof ConfigurableBeanFactory) {
                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
              }
              else {
                throw new NoSuchBeanDefinitionException(parentBeanName,
                    "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                    "': cannot be resolved without an AbstractBeanFactory parent");
              }
            }
          }
          catch (NoSuchBeanDefinitionException ex) {
            throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
          }
          // Deep copy with overridden values.
          //创建新的,并覆盖原来的RootBeanDefinition
          mbd = new RootBeanDefinition(pbd);
          //设置被覆盖的bean定义
          mbd.overrideFrom(bd);
        }
        // Set default singleton scope, if not configured before.
        //如果没有配置Scope属性,则默认按单例处理
        if (!StringUtils.hasLength(mbd.getScope())) {
          mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
        }
        // A bean contained in a non-singleton bean cannot be a singleton itself.
        // Let's correct this on the fly here, since this might be the result of
        // parent-child merging for the outer bean, in which case the original inner bean
        // definition will not have inherited the merged outer bean's singleton status.
        if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
          //同步Scope属性值
          mbd.setScope(containingBd.getScope());
        }
        // Cache the merged bean definition for the time being
        // (it might still get re-merged later on in order to pick up metadata changes)
        if (containingBd == null && isCacheBeanMetadata()) {
          //存储到缓存中
          this.mergedBeanDefinitions.put(beanName, mbd);
        }
      }
      //如果原先的定义信息不为空,则拷贝部分先前的属性值到当前的合并的定义中
      if (previous != null) {
        copyRelevantMergedBeanDefinitionCaches(previous, mbd);
      }
      return mbd;
    }
  }

这里稍微整理一下:

1、如果当前的bean定义不存在父类,则判断当前定义是否为RootBeanDefinition,如果是则直接返回,不是则创建一个新的合并的Bean定义信息(RootBeanDefinition)。


2、如果存在父定义,并且父定义beanName与子定义信息的beanName不同时,则递归创建RootBeanDefinition,因为父类也存在父类,即子类有父类,爷爷类,太爷爷类。。。


3、如果父定义的beanName与自定义的beanName相同时,如果其父工厂为ConfigurableBeanFactory类型,则调用父工厂getMergedBeanDefinition方法,从父工厂中进行查找合并。


transformedBeanName(bd.getParentName()),见方法4详解

方法4:transformedBeanName

  protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
  }
  public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    //如果名称带不以&符号开头则直接返回
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
      return name;
    }
    //切割&符号后面的字符为beanName
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
      do {
        beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
      }
      while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
      return beanName;
    });
  }
  public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
      //从别名缓存中获取真正的beanName
      resolvedName = this.aliasMap.get(canonicalName);
      if (resolvedName != null) {
        canonicalName = resolvedName;
      }
    }
    while (resolvedName != null);
    return canonicalName;
  }

方法5:isFactoryBean

  public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
    //去除&前缀,通过别名获取beanName
    String beanName = transformedBeanName(name);
    //尝试从缓存中获取
    Object beanInstance = getSingleton(beanName, false);
    if (beanInstance != null) {
      //判断是否实现了FactoryBean接口
      return (beanInstance instanceof FactoryBean);
    }
    //如果bean定义缓存中没有存在该beanName 并且 其父类工厂是一个ConfigurableBeanFactory
    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
      // 从父工厂中寻找
      return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
    }
    return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
  }

整理下思路:

1、先将beanName去掉前缀,并尝试从别名缓存获取对应的beanName,通过beanName在三级缓存中查询是否已经实例化的对象,有则进行类型判断。


2、beanName在当前beanFactory中没有存在定义,并且该工厂存在父工厂且是ConfigurableBeanFactory类型,则在父工厂进行查找,也就是使用父工厂重新执行一遍isFactoryBean流程。


3、beanName在当前beanFactory工厂中存在定义,则进行解析判断。


getSingleton(beanName, false),见方法6详解


isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName)),见方法7详解

方法6:getSingleton

  protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //从一级缓存中获取,即成品缓存(完成了初始化过程即属性注入等)
    Object singletonObject = this.singletonObjects.get(beanName);
    //如果一级缓存获取不到,且在创建的缓存中存在时
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
        //从二级缓存中获取,即半成品缓存(完成了初始化,未实例化)
        singletonObject = this.earlySingletonObjects.get(beanName);
        //二级缓存中不存在,并且允许提前引用
        if (singletonObject == null && allowEarlyReference) {
          //从三级缓存中获取ObjectFactory对象
          ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
          if (singletonFactory != null) {
          //调用getObject获取实例,该实例也是半成品
            singletonObject = singletonFactory.getObject();
            //放入到二级缓存中
            this.earlySingletonObjects.put(beanName, singletonObject);
            //从三级缓存中移除
            this.singletonFactories.remove(beanName);
          }
        }
      }
    }
    return singletonObject;
  }

这个方法很重要,是解决循环依赖的组成部分。singletonObjects一级缓存、earlySingletonObjects二级缓存、singletonFactories三级缓存。这里简单介绍下循环依赖,现有A、B两个类,A中有B属性,B中也有A属性,当创建A后,对属性B进行注入时,会去创建B,对B进行属性注入时发现B中需要注入A属性,就会再创建A,这样就死循环了。


我们是否可以使用一级缓存解决循环依赖呢?

A实例化完成时,放入一级缓存中,当属性注入时去一级缓存中寻找B,找不到则创建B;实例化B后,放入一级缓存中,在对B进行属性注入时,从一级缓存中寻找A,找到后进行注入,这时候A再拿到B进行属性注入。这种方式也可以解决循环依赖,但是如果存在多线程,并且在创建过程中去获取A,而A此时的状态还是半成品,那就有问题了,而且如果A的AOP代理对象,那完全操作不了。


是否可以使用二级缓存解决循环依赖呢?

创建A后,放入二级缓存中,并从二级缓存查找B,找不到则创建B,B创建完成后放入二级缓存中,从二级缓存中查找A进行属性注入,这时候的B就是一个完整品,将其放入一级缓存中,再从二级缓存中移除。A从一级缓存中获取B,进行属性注入后,加入一级缓存,并且移除二级缓存中的半成品。有了二级缓存后,就可以解决多线程获取的问题。但是如果A被AOP进行代理,A刚开始创建时肯定是一个原始对象(未被代理的),所以B在进行属性注入时从二级缓存中拿出来的注入的对象就是未被代理的A了,那这样也有问题了。


三级缓存解决循环依赖:

创建A后,我们往三级缓存中存入ObjectFactory类型的包装类A,此getObject方法实现如下代码所示(会提前调用AOP代理生成代理对象);属性注入时,会创建B,B会往三级缓存中存入ObjectFactory类型的包装类B,进行属性注入时,从一级缓存中获取A,取不到从二级中缓存,取不到从三级缓存获取,调用getObject方法获取代理后的A对象,并存入二级缓存中,移除三级缓存数据,此时B对象就是一个完整的对象,并且其属性A也是一个代理后的对象,加入一级缓存,移除二级缓存(如果B还有引用其它属性如C,C中也引用了B时,会存在数据)、三级缓存。此时A获取到B对象后进行注入,添加到一级缓存中,并移除二级缓存、三级缓存数据。

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

方法7:isFactoryBean

  protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
    //判断是否是FactoryBean
    Boolean result = mbd.isFactoryBean;
    if (result == null) {
      //获取class对象
      Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
      //判断是否是FactoryBean或其子类实现
      result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
      mbd.isFactoryBean = result;
    }
    return result;
  }

总结

本篇文章讲解了bean创建前的准备工作,及其FactoryBean的概念,并且讲解了三级缓存的作用。


一级缓存 singletonObjects:存放完整的Bean对象


二级缓存 earlySingletonObjects:存放半成品Bean对象


三级缓存singletonFactories:存放封装后的ObjectFactory,通过getObject返回实例对象,该对象可能是代理后的对象也可能是普通对象。

————————————————

版权声明:本文为CSDN博主「@猪大肠」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_45031612/article/details/127989693

目录
相关文章
|
20天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
20天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
20天前
|
XML 缓存 Java
手写Spring源码(简化版)
Spring包下的类、手写@ComponentScan注解、@Component注解、@Autowired注解、@Scope注解、手写BeanDefinition、BeanNameAware、InitializingBean、BeanPostProcessor 、手写AnnotationConfigApplicationContext
手写Spring源码(简化版)
|
20天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
118 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
8天前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
5天前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
15 4
|
10天前
|
XML 缓存 Java
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
39 10
|
10天前
|
XML 存储 Java
spring源码刨析-spring-beans(内部核心组件,beanDefinition加载过程)
spring源码刨析-spring-beans(内部核心组件,beanDefinition加载过程)
|
8天前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
30 3
|
10天前
|
XML 存储 Java
Spring-源码深入分析(二)
Spring-源码深入分析(二)
下一篇
无影云桌面