Chinaunix首页 | 论坛 | 博客
  • 博客访问: 56368
  • 博文数量: 22
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 221
  • 用 户 组: 普通用户
  • 注册时间: 2015-08-28 11:18
文章分类

全部博文(22)

文章存档

2021年(4)

2020年(1)

2016年(10)

2015年(7)

我的朋友

分类: Java

2021-09-23 19:39:43

核心类:DefaultSingletonBeanRegistry


循环依赖问题的解决方案:


DefaultSingetonBeanRegistry 的三级缓存


/** Cache of singleton objects: bean name to bean instance. */。一级缓存

private final Map singletonObjects = new ConcurrentHashMap<>(256);


/** Cache of singleton factories: bean name to ObjectFactory. */  三级缓存

private final Map> singletonFactories = new HashMap<>(16);


/** Cache of early singleton objects: bean name to bean instance. */。二级缓存

private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);


三个级别的缓存存放顺序是3 2 1  查找顺序是 1 2 3


1.三级缓存解决循环依赖问题的关键是什么?为什么通过提前暴露对象能够解决问题。


实例化和初始化分开操作,在中间过程中给其他对象赋值的时候,并不是一个完整对象,而是把半成品(完成实例化,但是没有完成初始化)对象赋值给了其他对象。


2.如果只使用一级缓存能不能解决这个问题


不能。在整个处理过程中,缓存中存放的是半成品和成品对象,如果只有一级缓存,那么半成品和成品都会放到一级缓存中。有可能在获取过程中获取到半成品对象,此时半成品对象是无法使用的,不能直接进行相关处理,因此需要把半成品和成品的存放空间分割开来。


3.只使用二级缓存行不行?为什么需要三级缓存

如果能保证所有的bean对象都不去调用getEarlyBeanReference方法,因为三级缓存中存放的就是beanName->getEarlyBeanReference,就可以不用三级缓存。只是使用二级缓存就可以。


使用三级缓存的本质是解决AOP代理问题!!!


4.如果某个Bean对象代理对象,会不会创建普通的bean对象?

会,首先会创建普通对象,然后依据条件查看是否符合代理条件,如果符合的话,会使用代理对象将普通对象覆盖掉。


/**

 * Obtain a reference for early access to the specified bean,

 * typically for the purpose of resolving a circular reference.

 * @param beanName the name of the bean (for error handling purposes)

 * @param mbd the merged bean definition for the bean

 * @param bean the raw bean instance

 * @return the object to expose as bean reference

 */

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {

Object exposedObject = bean;

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {

exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);

}

}

return exposedObject;

}


5.使用了三级缓存就可以解决这个问题?

当一个对象需要被代理的时候,在整个创建过程中是包含了两个对象。一个是普通对象,一个是代理生成的对象。bean默认都是单例。那么我们在整个生命周期的处理过程,一个beanname能对应两个bean对象吗?不能,既然不能的话,保证我在使用的时候,加一层判断,判断是否需要进行代理的处理。


6.我怎么知道你什么时候使用呢?

因为不知道什么时候进行调用,所以通过一个匿名内部类的方式,在使用的时候直接对普通对象进行覆盖操作。保证全局唯一。



1.一级缓存放置成品对象

2.二级缓存放置半成品对象

3.三级缓存放置lambda表达式,来完成代理对象的覆盖过程

阅读(280) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~