《Spring源码深度解析》学习笔记-bean的加载
对于bean的加载,在spring中的调用方式为:
MyTestBean bean=(MyTestBean) bf.getBean("myTestBean");
根据上图,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的使用
2.缓存中获取单例bean
3.从bean的实例中获取对象
4.获取单例
缓存中不存在已经加载的的单例bean就需要从头开始bean的加载过程,
Spring使用getSingleton的重载方法实现bean的加载过程
5.准备创建bean
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)实例化策略
处理循环依赖图:
populateBean函数:
InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation函数—可控制程序是否继续进行属性填充
根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中。
应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理
将所有PropertyValues中的属性填充至BeanWrapper中
applyPropertyValues函数:将PropertyValues属性应用到已经实例化的bean中
浅拷贝:被复制的对象的所有的变量都与原对象有相同的值,而所有的引用对象仍然指向原来的对象。
换言之,浅拷贝只是复制所考虑的对象,不复制引用对象。
深拷贝:深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。
当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
初始化bean:激活Aware方法--处理器应用--激活自定义的init方法
注册DisposableBean