Spring的三级缓存解决循环依赖问题
为了更好的理解循环依赖的问题,我们先一点一点手写循环依赖的代码
模拟spring的getBean简易流程,首先是只有一级缓存,
public class Criculation {
//一级缓存
private static HashMap<String, Object> singletonMap = new HashMap<String, Object> ();
//bean定义的Map
private static HashMap<String, RootBeanDefinition> beanDefinitionMap = new HashMap<> ();
public static void main(String[] args) throws Exception {
// InstanceA和InstanceB两个beanDefinition
RootBeanDefinition beanDefinitionA = new RootBeanDefinition (InstanceA.class);
RootBeanDefinition beanDefinitionB = new RootBeanDefinition (InstanceB.class);
//beanDefinitionMap存放beanDefinition
beanDefinitionMap.put ("instanceA", beanDefinitionA);
beanDefinitionMap.put ("instanceB", beanDefinitionB);
Object instanceA = getBean ("instanceA");
// ((InstanceA)instanceA).hello ();
((InstanceB)singletonMap.get("instanceB")).getInstanceA ().hello ();
}
//getBean方法获取bean
public static Object getBean(String beanName) throws Exception {
//首先向一级缓存获取bean,如果获取到直接返回
Object bean = singletonMap.get (beanName);
if (bean != null) {
return bean;
}
//从beanDefinitionMap中获取对应的beanDefinition
RootBeanDefinition rootBeanDefinition = beanDefinitionMap.get (beanName);
//因为是模拟,直接使用了无参构造器获取bean实例,此时bean属性没有赋值
Class<?> beanClass = rootBeanDefinition.getBeanClass ();
Object instanceBean = beanClass.newInstance ();
Field[] declaredFields = beanClass.getDeclaredFields ();
//这样解决循环依赖,最终得到的InstanceA的成员变量instanceB指向InstanceB而
//InstanceB的成员变量instanceA指向InstanceA形成了环
//为什么解决了循环依赖,就是InstanceB再依赖InstanceA之前先从一级缓存中获取,此时的InstanceA只实例化,没有属性赋值,就是下面这个代码,在没有赋值之前就将InstanceA放到一级缓存中
singletonMap.put (beanName, instanceBean);
//遍历属性
Arrays.stream (declaredFields).forEach (o -> {
//如果属性标注了Autowired注解,则getBean获取实例
Annotation annotation = o.getAnnotation (Autowired.class);
if (annotation != null) {
try {
Object beanField = getBean (o.getName ());
//有可能是private
o.setAccessible (true);
//为属性赋值
o.set (instanceBean, beanField);
} catch (Exception e) {
e.printStackTrace ();
}
}
});
//把bean放到一级缓存中,这段代码上面也有,如果放在上面可以解决循环依赖,如果不能理解,可以用debug的模式跟代码 就能明白
//如果放在这的话,抛出栈溢出的异常
singletonMap.put (beanName, instanceBean);
return instanceBean;
}
}
//两个循环依赖的类
@Data
class InstanceA {
@Autowired
private InstanceB instanceB;
public void hello(){
System.out.println ("hello");
}
}
@Data
class InstanceB {
@Autowired
private InstanceA instanceA;
}
两个类的关系如下图,红色部分为toString方法的异常,因为toString是要打印类实例化的信息,包含所有的成员变量,因为变量是相互的指向,所以调用toSting的时候,出现栈溢出错误,
只有一级缓存有能力解决循环依赖,但是出现了不完整Bean的真空期(实例化后先放到容器中再赋值),如果是多线程的话,在一级缓存中可能获取到的bean是不完整的,可以考虑将不完整的bean放到二级缓存中.
public class Criculation {
//一级缓存
private static HashMap<String, Object> singletonMap = new HashMap<String, Object> ();
//二级缓存
private static HashMap<String, Object> earlySingletonMap = new HashMap<String, Object> ();
//bean定义的Map
private static HashMap<String, RootBeanDefinition> beanDefinitionMap = new HashMap<> ();
public static void main(String[] args) throws Exception {
RootBeanDefinition beanDefinitionA = new RootBeanDefinition (InstanceA.class);
RootBeanDefinition beanDefinitionB = new RootBeanDefinition (InstanceB.class);
beanDefinitionMap.put ("instanceA", beanDefinitionA);
beanDefinitionMap.put ("instanceB", beanDefinitionB);
Object instanceA = getBean ("instanceA");
((InstanceA)instanceA).hello ();
}
public static Object getBean(String beanName) throws Exception {
//一级缓存中获取完整bean
if (singletonMap.containsKey (beanName)) {
return singletonMap.get (beanName);
//二级缓存中获取的bean为不完成的bean,解决循环依赖
} else if (earlySingletonMap.containsKey (beanName)) {
return earlySingletonMap.get (beanName);
}
RootBeanDefinition rootBeanDefinition = beanDefinitionMap.get (beanName);
Class<?> beanClass = rootBeanDefinition.getBeanClass ();
Object instanceBean = beanClass.newInstance ();
Field[] declaredFields = beanClass.getDeclaredFields ();
//将实例化但是没有属性赋值bean放到二级缓存中
earlySingletonMap.put (beanName, instanceBean);
Arrays.stream (declaredFields).forEach (o -> {
Annotation annotation = o.getAnnotation (Autowired.class);
if (annotation != null) {
try {
Object beanField = getBean (o.getName ());
o.setAccessible (true);
o.set (instanceBean, beanField);
} catch (Exception e) {
e.printStackTrace ();
}
}
});
//将完整的bean放到一级缓存中
singletonMap.put (beanName, instanceBean);
return instanceBean;
}
}
@Data
class InstanceA {
@Autowired
private InstanceB instanceB;
public void hello() {
System.out.println ("hello");
}
}
@Data
class InstanceB {
@Autowired
private InstanceA instanceA;
}
当然得到的结果和上面的图片是一样的.
下面是三级缓存,高度还原了spring的源码,源码中实例化和属性赋值都是通过bean的后置处理器实现的,为了解耦,本实例采用的是无参构造器反射实例化,赋值直接为@Autowired属性赋值,
DefaultBeanFactory类
public class DefaultBeanFactory extends SingletonBeanRegistry {
//存放bean定义
private final Map<String, RootBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<> ();
public void registerBeanDefinition(String beanName, RootBeanDefinition beanDefinition) {
this.beanDefinitionMap.put (beanName, beanDefinition);
}
public Object getBean(String name) throws Exception {
return doGetBean (name);
}
private <T> T doGetBean(String beanName) throws Exception {
Object bean;
//获取bean
Object sharedInstance = getSingleton (beanName, true);
if (sharedInstance != null) {
bean = sharedInstance;
} else {
//一级缓存没有bean,创建bean,首先获取bean定义
RootBeanDefinition beanDefinition = this.beanDefinitionMap.get (beanName);
if (beanDefinition == null) {
throw new AssociationException ("can not find the definition of bean '" + beanName + "'");
}
//创建bean并属性赋值
bean = getSingleton (beanName, () -> {
try {
return doCreateBean (beanName, beanDefinition);
} catch (BeansException ex) {
removeSingleton (beanName);
throw ex;
}
});
}
return ( T ) bean;
}
private Object doCreateBean(String beanName, RootBeanDefinition beanDefinition) throws BeansException {
//创建实例,这里只是用了无参构造器
Object bean = createBeanInstance (beanName, beanDefinition);
boolean earlySingletonExposure = isSingletonCurrentlyInCreation (beanName);
if (earlySingletonExposure) {
addSingletonFactory (beanName, () -> bean);
}
Object exposedObject = bean;
//属性赋值
populateBean (beanName, beanDefinition, bean);
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton (beanName, false);
if (earlySingletonReference != null) {
exposedObject = earlySingletonReference;
}
}
return exposedObject;
}
/** createBeanInstance方法在源码中的实现方式
* AbstractAutowireCapableBeanFactory#createBeanInstance
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);获取构造函数
autowireConstructor(beanName, mbd, ctors, null);通过有参构造创建bean实例(未初始化)
instantiateBean(beanName, mbd);通过无参构造创建bean(未初始换)*/
private Object createBeanInstance(String beanName, RootBeanDefinition beanDefinition) throws BeansException {
Class<?> beanClass = beanDefinition.getBeanClass ();
Constructor<?> constructorToUse;
if (beanClass.isInterface ()) {
throw new BeanCreationException ("Specified class '" + beanName + "' is an interface");
}
try {
constructorToUse = beanClass.getDeclaredConstructor (( Class<?>[] ) null);
constructorToUse.setAccessible (true);
return constructorToUse.newInstance ();
} catch (Exception e) {
throw new BeanCreationException ("'" + beanName + "',No default constructor found", e);
}
}
/**
* 源码中populateBean方法是通过下面两个bean后置处理器为属性赋值
AutowiredAnnotationBeanPostProcessor#postProcessProperties 为@Autowired和@Value赋值
CommonAnnotationBeanPostProcessor#postProcessProperties 为@Resource赋值
*/
private void populateBean(String beanName, RootBeanDefinition beanDefinition, Object beanInstance) {
Field[] beanFields = beanDefinition.getBeanClass ().getDeclaredFields ();
Arrays.stream (beanFields).forEach (o -> {
Annotation annotation = o.getAnnotation (Autowired.class);
if (annotation != null) {
try {
Object beanField = getBean (o.getName ());
o.setAccessible (true);
o.set (beanInstance, beanField);
} catch (Exception e) {
e.printStackTrace ();
}
}
});
}
}
SingletonBeanRegistry类
public class SingletonBeanRegistry {
private static final Object NULL_OBJECT = new Object();
//一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
//二级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>();
//三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
//正在创建标识
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>());
protected Object getSingleton(String beanName,boolean allowEarlyReference) {
//从一级缓存获取完整bean
Object singletonObject = this.singletonObjects.get(beanName);
//一级缓存为空,并且正在创建,出现循环依赖的情况
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存为空,allowEarlyReference为true 利用三级缓存创建bean
if (singletonObject == null && allowEarlyReference) {
//从三级缓存获取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果不为空
if (singletonFactory != null) {
//调用了函数接口,其实也是直接返回bean
singletonObject = singletonFactory.getObject();
//存放进二级缓存,这里及存在了线程安全问题
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
protected Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
//从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//添加到正在创建集合
this.singletonsCurrentlyInCreation.add(beanName);
//调用doCreateBean方法
singletonObject = singletonFactory.getObject();
//从正在创建集合移除
this.singletonsCurrentlyInCreation.remove(beanName);
//添加到一级缓存,从二级三级缓存中移除
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
}
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
}
}
}
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
}
}
protected boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
}
测试代码
public class MainTest {
public static void main(String[] args) throws Exception {
RootBeanDefinition beanDefinitionA = new RootBeanDefinition();
beanDefinitionA.setBeanClass (InstanceA.class);
RootBeanDefinition beanDefinitionB = new RootBeanDefinition();
beanDefinitionB.setBeanClass (InstanceB.class);
DefaultBeanFactory defaultBeanFactory = new DefaultBeanFactory ();
defaultBeanFactory.registerBeanDefinition ("instanceA",beanDefinitionA);
defaultBeanFactory.registerBeanDefinition ("instanceB",beanDefinitionB);
Object instanceA = defaultBeanFactory.getBean ("instanceA");
}
}
@Data
class InstanceA {
@Autowired
private InstanceB instanceB;
public InstanceA() {
System.out.println ("InstanceA初始化");
}
}
@Data
class InstanceB {
@Autowired
private InstanceA instanceA;
public InstanceB() {
System.out.println ("InstanceB初始化");
}
}
第三级缓存都是存放的lambda表达式,也是解耦
代码的分析用下面的图简单的讲解一下,可以结合debuger 一点点调试
在第四张图如果此时线程2创建InstanceA的话,二级缓存中有不完整的实例,并且正在创建队列中含有InstanceA
Object sharedInstance = getSingleton (beanName, true);直接返回的就是InstanceA的不完成实例所以使用synchronized加锁,保证线程安全.
一级缓存和三级缓存不管是否是循环依赖都要使用,只要在循环依赖的情况下才会使用到二级缓存,加锁的方式防止多线程从二级缓存中获取没有初始化好的类.