spring底层
bean的加载
xml->获取io流->解析xml->获取document->获取斧子节点->设置到beandefinition中
beanFactory
如果要访问容器的话必须要经过beanFactory
常用的ApplicationContext就继承自BeanFactory(BeanFactory为根接口)
BeanFactoryPostProcessor其中有个子类在解析xml时会去替换占位符
bean的生命周期
- 实例化:在内存中开辟空间
- 初始化:属性赋值
- 使用对象
- 销毁对象
bean会保存到一个map中去
DefaultSingletonBeanRegistry中有几个map
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);//一级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);//三级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap(16);//二级缓存
实例化
在堆中申请内存,属性值默认值
调用createBeanInstance
反射
- class对象
- 构造器
- new Instance
设置(自定义)属性
这个属性是设置自定义属性
populateBean调用set方法赋值
调用aware相关接口
调用aware相关接口,设置相关依赖
这个属性是设置容器属性
invokeAwareMEthods
Aware是检查当前接口是否为容器接口的
初始化
执行前置后置处理方法
BeanPostProcessor有俩个方法postProcessBeforeInitialization和postProcessAfterInitialization
AOP用动态代理去初始化类
默认后置进行了AOP 动态代理 1,jdk动态代理, 2cglib动态代理
前置默认无操作
postProcessBeforeInitialization->invokeInitMethods->后置 postProcessAfterInitialization
invokeInitMethods
判断bean是否实现了InitializingBean接口,如果实现了调用afterPropertiesSet
中间的为调用初始化方法
在配置bean时会指定init-method
把对象交给容器管理
调用getSingleton方法,调用了addSingleton,(sync方法)
将映射关系添加到一级缓存中
容器就可以进行管理起来了
销毁
很少使用context.clase()销毁对象,一般很少使用
beanFactory和factoryBean的区别
benaFactory:
必须遵循完整的bean的生命周期去创建对象
较为复杂,流水线式的创建对象
BeanFactory 是底层的Ioc容器,ApplicationContext 继承了它,并增加了一些特性。在实现方面,ApplicationContext 组合了一个 BeanFactory 的实现,使用这个实现对象来完成一些操作。
factoryBean
FactoryBean也是接口,为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式(如果想了解装饰模式参考:修饰者模式(装饰者模式,Decoration)我们可以在getObject()方法中灵活配置。其实在Spring源码中有很多FactoryBean的实现类.
创建对象,没有标准的流程,私人订制,用自己的方式去创建对象
方法
isSingleton:判断是否是单例
getObjectType:返回对象的类型
getObject:返回对象
循环依赖
逻辑
spring的默认对象是单例的
比如A与B俩个对象是循环依赖的
一般如图所示
对象分为俩种
成品对象:完成实例化且完成初始化
半成品:完成实例化
在b判断容器中是否有a对象时
三级缓存解决循环依赖
解决思路:在实例化对象之后放入一个map中,一个map放半成品,一个map放成品对象
当需要创建对象的时候先去半成品的map中取,去半成品map中进行赋值,赋值完成变为成品对象后继续初始化
源码中的定义
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);//一级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);//三级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap(16);//二级缓存
一级和二级缓存是concurrentHashMap,三级HashMap
他们的初始容量也不一样
一级二级放的是Object三级中放的是ObjectFactory
ObjectFactory定义
@FunctionalInterface
public interface ObjectFactory<T> {
T getObject() throws BeansException;
}
ObjectFactory是一个函数式接口,有且仅有一个方法,可以当做方法的参数传递进去,当指名此类型参数的方法,可以传入一个lambda表达式,在执行的时候并不会执行lambda表达式,在调用getObject()方法的时候才会去调用lambda的处理逻辑
调用逻辑
- getBean:先判断容器里是否有对象,之后进行getBean
- doGetBean:实际获取bean的方法,在其中会用getSingleton获取对象判断缓存中是否有注册单例的对象
- createBean:执行getSingleton,传入lambda表达式(不会立刻执行)
- doCreateBean:实际创建bean对象的逻辑
- createBeanInstance创建bean实例(到这里完成了实例化a对象)
之后将会执行addSingletonFactory,方法向三级缓存中put包含当前对象的lambda表达式,然后清空2级缓存
(最后将beanNAme添加已注册的单例集合中,和三级缓存无关)
- populateBean:填充属性,如果没有获取到属性对象,就去容器中获取,先去一级缓存中获取,获取不到的话,去二级获取不到去三级获取(getObject).如果在三级缓存中没有,就去创建对象重走逻辑.如果在三级缓存中取到了,就返回经过层次包装后的对象,然后将当前创建的对象放入二级缓存中,删除原来三级缓存中的b(在二级缓存中的对象依旧是半成品,删除三级缓存是因为,二级缓存有了就不会查找三级缓存了).对象整个创建完毕变为成品对象后,会移除二级三级缓存,放入到一级缓存之中
比如AB存在循环引用
先创建A对象->判断是否有注册->初始化->放入三级缓存->注入属性(B对象)->获取去三级缓存中获取b对象->为获取到->创建b对象->初始化->放入三级缓存->注入属性(A对象)->去获取三级缓存中的A对象(经过层次包装后的对象)->成功获取到A对象->将A对象放到二级缓存中(此时A依旧是半成品)->清除三级缓存(二级缓存有了就不会查询三级缓存了)->B对象变为成品对象->b对象放入一级缓存中->获取到b对象->给A对象中的b属性赋值->将A放入一级缓存->删除二级缓存->在一级缓存中获取到B对象,并给A设置
总结
三个map结构分别存储什么对象
一级缓存:成品
二级缓存:办成品
三级缓存lambda表达式
查找顺序
依次从一级缓存到三级缓存
思考
如果只有俩个map能否解决循环依赖的问题?
能但有前提条件,循环依赖中不包含aop的处理逻辑
为什么三级缓存可以解决循环依赖中包含的代理对象的问题?
创建代理对象的时候是否需要创建出原始对象?
- 需要
同一个容器中,能否出现同名的俩个不同对象
- 不能
如果一个对象被代理,那么代理对象和原始对象该如何进行存储
- 如果需要代理对象,那么代理对象创建完成之后应该覆盖原始对象
在getEarlyBeanReference方法中会判断是否需要代理对象,如果创建出代理对象了,那么就需要覆盖
- 如果需要代理对象,那么代理对象创建完成之后应该覆盖原始对象
在对象对外暴露了的时候,如何准确的给出原始对象或者代理对象,(因为正常代理对象的创建是BeanPostProcessor的后置处理方法中,在解决循环依赖的问题的时候还没执行到那个地方)
- 此时需要lambda表达式了,类似于一种回调机制,在确定要对外暴露的时候,就唯一性的确定到底是代理对象还是原始对象,这也是为什么不把对象直接放到二级缓存中,而是通过三级缓存lambda表达式的方式来执行原因
简单来说什么时候需要对外暴露,程序没办法确定,而lambda表达式在被调用时才会去执行,确定返回的是代理对象还是原始对象
为什么spring提供了一个循环依赖的解决机制,但是业务中还会遇到循环依赖问题呢?
spring是一个跟业务无关的技术框架,只能预防一些问题,而不是解决所有问题
spring中的设计模式
- 单例模式:spring中的bean默认都是单例
- 工厂模式:BeanFacotry
- 模板方法:postProcessorBeanFactory,onRefresh(留给扩展子类来进行实现的)
- 观察者模式:Wlistener,event,multicast
- 适配器模式Adapter
- 装饰器模式BeanWrapper
- 责任链模式:使用aop的时候会有一个链式责任
- 代理模式:aop动态代理
- 委托者模式:delegate
- 建造者模式:builder
- 策略模式:XmlBeanDefinittionReader,PropertiesBeanDefinitionReader