《Spring源码深度解析》学习笔记-bean的加载

对于bean的加载,在spring中的调用方式为:
    MyTestBean bean=(MyTestBean) bf.getBean("myTestBean");

《Spring源码深度解析》学习笔记-bean的加载_第1张图片
    
根据上图,Spring加载Bean的大致过程:
    1.转换对应的beanName(其实就是获取真正的beanName),因为传入的beanName可能是别名或者FactoryBean
        去除FactoryBean的修饰符,也就是如果name="&aa" 那么首先会去除&而使name="aa"
        取指定的alias所表示的最终beanName,A指向名称为B的bean则返回B
    2.尝试从缓存中加载单例(循环依赖)
    
    3.bean的实例化
        从缓存中得到bean的原始状态,则需要对bean进行实例化
        
    4.原型模式的依赖检查
    
    5.检查parentBeanFactory:
        缓存中不存在则到父类工厂中加载
        
    6.将存储XML的配置文件的GenericBeanDefinition转换为RootBeanDefinition
    
    7.寻找依赖:加载bean之前首先初始化该bean对应的依赖
    
    8.针对不同的scope进行bean的创建
    
    9.类型转换
----------------------------------------------------------------------------------------------------------------    


1.FactoryBean的使用
    《Spring源码深度解析》学习笔记-bean的加载_第2张图片
2.缓存中获取单例bean
    《Spring源码深度解析》学习笔记-bean的加载_第3张图片
3.从bean的实例中获取对象

《Spring源码深度解析》学习笔记-bean的加载_第4张图片

《Spring源码深度解析》学习笔记-bean的加载_第5张图片

《Spring源码深度解析》学习笔记-bean的加载_第6张图片

4.获取单例
    缓存中不存在已经加载的的单例bean就需要从头开始bean的加载过程,
    Spring使用getSingleton的重载方法实现bean的加载过程

《Spring源码深度解析》学习笔记-bean的加载_第7张图片

5.准备创建bean

《Spring源码深度解析》学习笔记-bean的加载_第8张图片

《Spring源码深度解析》学习笔记-bean的加载_第9张图片

《Spring源码深度解析》学习笔记-bean的加载_第10张图片

 

6.循环依赖
    定义:循环依赖即循环引用,就是两个或多个bean相互之间的持有对方,
        比如类A引用类B,类B引用类C,类C引用类A,它们最终反映为一个环。
        此处不是循环调用,循环调用是方法之间的环调用,循环调用无解,
        除非有终结条件,否则死循环,内存溢出。
    解决:Spring循环依赖包括构造器循环依赖和setter循环依赖,处理分三张情况
        1)构造器循环依赖:通过构造器注入构成的循环依赖,此依赖无法解决,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。
            eg:创建TestA类时,构造器需要TestB类,那将去创建TestB类,在创建TestB类时又发现需要TestC类,则又去创建TestC类,最终创
            建TestC类时又需要TestA类,从而形成一个环,没办法创建。
            Spring容器将每一个正在创建的bean标识符放到“当前创建bean池”中,bean标识符在创建过程中将一直保持在这个池中,因此如果在
            创建bean的过程中发现自己已经在“当前创建bean池”里,则抛出BeanCurrentlyInCreationException异常表示循环依赖,而对于已经
            创建完毕的bean将从“当前创建bean池”中清除掉。
        
        2)setter循环依赖:通过setter注入方式构成的循环依赖。对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器的注入但
            未完成其他步骤的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法(return getEarlyBeanReference()),
            从而使其他bean能引用到该bean。

7.创建bean

    1)autowireConstructor 构造函数及参数匹配
    2)instantiateBean 无参构造函数 直接调用实例化策略进行实例化
    3)实例化策略
    《Spring源码深度解析》学习笔记-bean的加载_第11张图片
《Spring源码深度解析》学习笔记-bean的加载_第12张图片    《Spring源码深度解析》学习笔记-bean的加载_第13张图片

《Spring源码深度解析》学习笔记-bean的加载_第14张图片

《Spring源码深度解析》学习笔记-bean的加载_第15张图片

处理循环依赖图:
    《Spring源码深度解析》学习笔记-bean的加载_第16张图片
    populateBean函数:
        InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation函数—可控制程序是否继续进行属性填充
        根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中。
        应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理
        将所有PropertyValues中的属性填充至BeanWrapper中
    《Spring源码深度解析》学习笔记-bean的加载_第17张图片
    《Spring源码深度解析》学习笔记-bean的加载_第18张图片
    applyPropertyValues函数:将PropertyValues属性应用到已经实例化的bean中
    《Spring源码深度解析》学习笔记-bean的加载_第19张图片
    浅拷贝:被复制的对象的所有的变量都与原对象有相同的值,而所有的引用对象仍然指向原来的对象。
        换言之,浅拷贝只是复制所考虑的对象,不复制引用对象。
    深拷贝:深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。
        当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
    
    
    初始化bean:激活Aware方法--处理器应用--激活自定义的init方法
        《Spring源码深度解析》学习笔记-bean的加载_第20张图片
    注册DisposableBean

《Spring源码深度解析》学习笔记-bean的加载_第21张图片
 

你可能感兴趣的:(Spring)