乐趣区

beanfactory中单例bean的初始化过程一

Date 10.06 pm

Point

完成 beanfactory 中单例 bean 的初始化

beanFactory.preInstantiateSingletons()

  1. 拿到所有的 bean 定义信息(在 beanDefinitionNames中,遍历 list
  2. 获取到 bean 的定义信息
  3. 如果这个 bean 不是抽象,是单例,不是懒加载的
  4. 判断这个 bean 是否 factorybean(判断这个 bean 有没有实现 factoryBean 接口),是的话,用工厂里面的方法去创建 bean。

    • 调用getbean(&beanname) 获取到 beanFactory 对象。
  5. 调用 getBean(beanName) 创建 bean

    • 调用 doGetBean()
    • transformedBeanName进入这个方法将之前工厂 bean 的前缀去除,将别名转成正式的名称
    • getSingleton检测单例缓存中是否有已构建的单实例 bean,有就直接返回这个单例 bean

      /** Cache of singleton objects: bean name to bean instance. */
      private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

      所有实例过的单例 bean 都会在这注册,检查的时候还会判断当前 bean 有没有在创建过程中。如果有的话,会在 earlySingletonObjects 去获取,要是这个还是没有获取到的话,会去 singletonFactories 这个 map 中去获取,要是获取到的话就删除 singletonFactories 中的 bean,转而在 earlySingletonObjects 这个 map 里面去注册

    • 没有获取到 bean(开始创建 bean 的流程)

      • 就先判断下我们是不是正在创建这个 bean 的实例,避免循环引用的问题。
      • 获取 bean 的父工厂(这个主要是如果有 Springmvc 的话 可能会有这种父子工厂)这个父工厂要是能获取到的话,又会去调用父工厂的 dogetbean 方法,获取不到父工厂的话直接下一步
      • 标记当前 bean 已经创建,大概就是把当前 beanname 放到 Collections.newSetFromMap(new ConcurrentHashMap<>(256)) 里面,防止多线程的时候多次创建单例 bean
      • 获取 bean 的定义信息
      • 获取 bean 所依赖的其他 bean,如果有,还是调用 getbean 的方式去构建那些依赖的 bean
      • 如果这个 bean 是单例 bean,回掉createBean,开始单例 bean 创建

        • 拿到 bean 的定义信息
        • 解析 bean 的定义的类型,检查这个定义信息中的 beanClass 是不是为空
        • 检测是否有 bean 方法被重写,有的话准备重写这个 bean 方法(也是检查 bean 定义信息里面的 methodOverrides 这个属性有没有值)
        • 让 BeanPostProcessor 提前拦截,返回代理对象resolveBeforeInstantiation()

          • 先根据定义信息中的 beforeInstantiationResolved 判断初始化之前有没有处理,有的话就不进入这个 processor 中了,
          • 然后判断这个值是不是由 application 定义的 和 判断当前 factory 中已经有了 InstantiationAwareBeanPostProcessor 这个 processor 了,然后去获取这个 bean 的目标 class,然后调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 启动前置处理器,然后如果返回的 bean 有值的话,再调用 applyBeanPostProcessorsAfterInitialization 后置处理器,然后将 bean 定义信息中 beforeInstantiationResolved 这个参数赋值成这个返回的 bean,然后返回这个 bean

https://github.com/fulln

退出移动版