发布网友 发布时间:2022-11-17 16:40
共1个回答
热心网友 时间:2024-07-28 16:56
从 Spring IOC 容器中获取 bean 实例的流程:从context.getBean()方法开始
*缓存为什么会移除掉?
在*缓存中找 找到了就会执行AOp 产出代理对象 然后将代理对象放入到二级缓存。*缓存一定会能到的对象 但不一定 会执行 aop 二级缓存找不到 才会触发aop(通过lambda表达式,执行函数式接口,执行aop) 产生代理对象放入二级缓存,放入之后需要移除掉对应的*缓存(保证只执行一次aop)如果*缓存中对象不需要执行aop操作 ,那么产生的对象仍然要放入二级缓存 ,这是放入的对象是原始对象
为什么单例池:concurentHashmap是,二级缓存是hashmap,*缓存是hashmap?
*缓存的AOP过程需要加锁以保证操作的原子性
因为*缓存的函数接口 内部已经加了锁,保证了操作的原子性 所以没必要使用concurenthashmap
问题:源码中加synchronized锁的意义?
背景:
二级缓存中的aService对象是*缓存中的lambda表达式生成出来的,
他们是成对的,二级缓存中存在代理对象,则*缓存中不应该存在lambda表达式;
或者说,*缓存中存在lambda表达式,则二级缓存中不应当有该代理对象
解答:
其中:
是将原始对象信息存入*缓存的操作,存入的是lambda表达式:
getEarlyBeanReference(beanName, mbd, bean)执行的结果,getEarlyBeanReference会对是否需要提前AOP进行判断,如果需要进行AOP,则生成代理对象放入二级缓存。
其中:
1、A doCreateBean()初始化,由于还未创建,从一级缓存查不到,此时只是一个半成品(提前暴露的对象),放入*缓存singletonFactories;
2、A发现自己需要B对象,但是*缓存中未发现B,创建B的原始对象,将带有B对象信息(beanName,bd,原始对象)的Lambda表达式放入singletonFactories;
3、B发现自己需要A对象,从一级缓存singletonObjects没找到,并知道了A对象正在创建,就确认发生了循环依赖,这时候再去二级缓存earlySingletonObjects中寻找A对象,没找到就继续在*缓存singletonFactories中寻找A对象(一定能找到),于是执行*缓存中的lambda表达式得到一个代理对象或者是原始对象A(A中属性未赋值),将A放入二级缓存earlySingletonObjects,同时从*缓存删除对应beanName的表达式;
同理向*缓存加入对象时,也会从二级缓存中将相同BeanName的记录删除掉,所以二级缓存与*缓存的之间的来两步操作具有原子性。
4、将A注入到对象B中;
5、B完成属性填充,执行初始化方法,将自己放入第一级缓存中(此时B是一个完整的对象);
6、A得到对象B,将B注入到A中;
7、A完成属性填充,初始化,并放入到一级缓存中
注意:在对象创建开始的时候,会对对象创建状态利用Set:
singletonsCurrentlyInCreation进行记录:是否是正在创建,可用于判断是否发生了循环依赖。
@Lazy注解的作用:
initializeBean
Spring解决循环依赖问题--B站视频讲解
Spring 循环依赖的“常见”面试问题