zoukankan      html  css  js  c++  java
  • 源码解析-SpringIOC容器初始化,Bean实例化过程

    本节重点分析Spring容器启动中 读取配置文件 解析一个个Bean封装成BeanDifinition注入到Map中 完成Bean的实例化过程(注意是实例化,并没有初始化)

    本节的重点就是 看到下obtainFreshBeanFactory()这个过程中做的事  

     

    源码分析

    这一阶段先记住ApplicationContext一个重要的子类  - AbstractRefreshableApplicationContext

    刷新工厂的操作有这货实现

    还是从new ClassPathXmlApplicationContext()入口看一下

     

     

     

    来了obtainFreshBeanFactory();

    1. obtainFreshBeanFactory()

     

    refreshBeanFactory();   // shutdown之前的工厂,开启一个新的工厂生命周期

    beanFactory = getBeanFactory();   // 获取BeanFactory,也就是上一步刚创建的BeanFactory这个是在AbstractRefreshableApplicationContext中的

    将这个beanFactory返回;

     

    先看一下getBeanFactory()实现

    先上了把锁,保证多线程串行获取

    返回这个beanFactory,默认是DefaultListableBeanFactory

    上节说过这个factory继承了上边全部Factory接口 也就是最叼的一个

     

    2. refreshBeanFactory()  销毁旧工厂 开启并初始化新工厂

     

    if (是否有factory了){

           //如果有就销毁所有的bean 然后关闭factory

    }

    try{

           DefaultListableBeanFactory beanFactory = 创建BeanFactory();

           设置一个序列化id;

           customizeBeanFactory();    定制beanFactory;

           锁{

                 把这个factory存下来

           }

     

    }

     

    3. createBeanFactory()  这个没啥好说的 就是new了一个DefaultListableBeanFactory()

    然后设置一下parentBeanFactory,默认是null的

     

     

    4. cusomizeBeanFactory(beanFactory);  定制刚创建的beanFactory

    是否允许bean被覆盖

    是否允许bean循环依赖

     

    5. loadBeanDefinitions 最重要的一步了,加载入bean的定义从XmlBeanDefinitionReader

    new 了一个XmlBeanDefinitionReader,把当前这个beanFactory设置进去;

    设置一些参数 姑且忽略;

     

    initBeanDefinitionReader(); //初始化Bean定义阅读器

    loadBeanDefinitions();       //加载  重点!!

     

    6.loadBeanDefinitions(XmlBeanDefinitionReader )  最重点的加载来了

     

     

    传入配置,for循环 每一个配置文件加载一次 记录count,继续往下

     

    重点了 从xml文件加载 bean definitions

    Set  surrentResources = 将当前resource配置源加载到ThreadLocal这里

    InputStream inputSream = 将配置源输入流获取到

    获取inputSource并配置编码集

    doLoadBeanDefinitions(inputSource)  真正干实事的在这

     

    从配置元将元素解析成Document树  //

    处理了各种异常情况

    return registerBeanDefinitions();   //注册成BeanDifinition

     

     

    6. 元素注册成BeanDefinitions,返回注册前后的数量差

    int countBefore = 注册之前的BeanDefinition的数量;

    注册;

    return 前后数量差;

     

    7. 从DOM元素中读取bean definitions,通过reader context注册他们

    获取根元素,开始注册

     

    根据根元素 注册每个bean definition

    别的都忽略 重点看parseBeanDefinitions(root, this.delegate); 将元素解析成Bean

     

    // default namespace 涉及到的就四个标签 <import />、<alias />、<bean /> 和 <beans />,

    // 其他的属于 custom 的

    namespace就是xml文件中的这个东东,默认是beans

    我们继续追下去

     

     

    将元素Ele 封装成一个beanDifinitionHolder (这一步很重要的,beanDifinitionHolder就是提供BeanDifinition的工具)

    注册最后的实例

    我们先来看一下这个beanDifinitionHolder

    三个属性 看一眼就明白了,他就是专门为提供beanDefinition而存在的

     

    8.parseBeanDefinitionElement()

     

    这个方法贼长分两段,

    上半段很简单就是获取一些id啊 name啊 别名啊这些东西 为实例化beanDefinition做准备

    下半段就是实例化beanDifinition,配置检验等一些事,最后将beanDefinition name 别名封装成一个holder  over

     

    8.再来 BeanDefinitionReaderUtils.registerBeanDefinition()

    String beanName = 通过definitionHolder获取bean的名称

    根据beanName注册BeanDefinition

     

    如果有别名,for循环别名 挨个注册

     

    9.registerBeanDefinition()  注册BeanDifinition的细节在这,挺老长的一个方法

    BeanName不能为null,BeanDefinition不能为null

    做一下检验(无法将静态工厂方法与方法重写结合使用)

     先尝试从map中获取一下beanDifination,看看是不是有重名的注册过了

    if(如果注册过同名beanDifination的话){

      if(看看配置里是否允许重名覆盖)

      该抛异常抛异常 该覆盖覆盖

      ...

      beanDefinitionMap.put() 最后put进来

    }

    else目前没有同名{

      if(是否有其他的bean开始初始化了) { //正常来说到目前为止所有的bean还处于注册阶段,正常来说在容器启动的最后会初始化所有singleton的bean,至于为什么这里会初始化俺不理解

        锁住map;

        put进去beanDefinition;

        List updatedDefinitions = new ArrayList(); 

        updatedDefinitons.addAll(beanNames集合);

        .add(beanName);

        再让beanNames集合 = updateDefinitions;    //这是什么操作?? 为哈不直接在beanNames.add

        如果手动注册的Set里已经有他了,再把他干掉;

      }else{

        //正常会进入到这了

        map.put();

        beanNames集合.add();

        手动注册的Set.remove()    

      }

    }

     

     差不多了,到这里已经把obtainFreshBeanFactory()这个方法做的事大概梳理了一下,

    1.创建工厂 DefaultListableBeanFactory

    2.加载配置文件中的元素信息

    3.封装成BeanDefinition,存入map保存起来

     

    到这里已经初始化了 Bean 容器,<bean /> 配置也相应的转换为了一个个 BeanDefinition,此时的Bean并没有初始化

     

     

  • 相关阅读:
    Mac小知识点
    UIScrollView直接在StoryBoard中拖控件
    iOS小工具
    iOS设备信息
    Android Studio stuck on “Gradle: resolve dependancies '_debugCompile'” or 'detachedConfiguration1'
    iOS开发插件集
    Include guards
    oc单例
    Java反射中与自动装箱有关的坑及其解决方案
    ByxAOP——简易AOP框架
  • 原文地址:https://www.cnblogs.com/ttaall/p/14533236.html
Copyright © 2011-2022 走看看