getBean(name)的描述

84 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

getBean(name);
  • 转换beanname,首先把 传入的beandefinition的名称转换成真正的bean的名称;

  • getSingleton(beanName),从三级缓存中获取bean;

【说明】

  • getSingleton的重载有个参数:allowEarlyReference===这个参数是解决循环依赖的标记;

     一级缓存 也就是单例缓存池 用于保存我们所有的单实例bean 
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
     三级缓存 该map用户缓存 key为 beanName  value 为ObjectFactory(包装为早期对象) 
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    二级缓存 ,用户缓存我们的key为beanName value是还未成熟的早期bean,还未赋值的bean 
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    
  • 执行该方法,先从一级缓存获取bean对象,一般来说,ioc容器中从一级缓存获取的bean是成熟的可以直接使用的;获取到bean直接返回;当首次加载时肯定是空的,因此走下面的逻辑;

  • 一级缓存未get到bean, 并且系统会根据一个临时集合list,根据beanname判断是否正在创建这个bean;

    private final Set<String> singletonsCurrentlyInCreation =
          Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    
  • 去到二级缓存中查找,二级缓存的是早期的未赋值的bean 因此在方法的开始传参true是允许早期对象的存在,要是还不存在

  • 从三级缓存中获取,三级缓存中获取 ObjectFactory对象 这就是用来解决循环依赖的关键,在ioc后期的过程中,当bean调用了构造方法的时候,把早期对象包裹成一个ObjectFactory暴露到三级缓存中;

  • 三级缓存存在则通过getObject方法获取早期bean放到二级缓存,从三级缓存删除函数bean;

  • 如果上面获取的Bean不是空,则继续判断当前bean的类型如果是普通bean则直接返回,如果是Factorybean则获取到真正的bean实例并返回;

    判断当前bean是不是实现了beanInstance instanceof FactoryBean 或者是否是& 开头的;来确定是不是普通bean,还是工厂bean继续向下获得真正的bean实例;

  • 获取单例bean getSingleton(beanName,o->{})

    • beforeSingletonCreation(beanName);

      创建bean之前,把beanname添加到singletonsCurrentlyInCreation 正在创建当前bean的集合中;

    • createBean()-----》doCreateBean(相当复杂的一个方法)创建bean

    • afterSingletonCreation(beanName);

      singletonsCurrentlyInCreation移除当前创建的beanname

    • addSingleton(beanName, singletonObject)

      把创建出来的bean添加到一级缓存,从二三级缓存移除,添加到已注册的set集合中;

doCreateBean

  • 首先就创建bean实例,creatbeanInstance();返回包装bean,从WrapperBean获取早期bean对象;

  • 接下来就是判断这个bean是否是单例的,是否允许循环依赖,是否是正在创建的ben,满足上述的三个条件则把bean添加到三级缓存;

  • 添加三级缓存:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));首先是单例缓存池没有该对象然后把它添加到三级缓存;

  • 三级缓存的FactoryObject通过函数式接口回调的方式添加:

    //TODO

  • 属性赋值populateBean

    • 首先判断当前容器中有没有InstantiationAwareBeanPostProcessor类型的后置处理器,我们可以通过postProcessAfterInstantiation方法自定义一些bean的信息;

    • 判断当前bean的注入方式:两种

      • AUTOWIRE_BY_NAME 根据名称注入

        获得 bean的所有属性对象,循环判断该属性对象是不是引用类型,是的话则通过getBean的方式获取;

        然后把bean之间互相的依赖关系注册起来; Map<String, Set> dependentBeanMap

      • AUTOWIRE_BY_TYPE 根据类型注入

  • 初始化exposedObject = initializeBean()bean的赋值操作;

    首先先进入invokeAwareMethods(beanName, bean)方法,判断是否实现了三个Aware接口;

    强转成相应的类型执行set方法;

    • BeanNameAware
    • BeanClassLoaderAware
    • BeanFactoryAware

    然后再是

    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
          //调用初始化方法
          invokeInitMethods(beanName, wrappedBean, mbd);
     
          wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);