diff --git a/docs/Spring/IoC/循环依赖.md b/docs/Spring/IoC/循环依赖.md index 9a68d75..d86972a 100644 --- a/docs/Spring/IoC/循环依赖.md +++ b/docs/Spring/IoC/循环依赖.md @@ -1,8 +1,8 @@ -## 循环依赖 +# 循环依赖 一个对象依赖对象闭环到自己 ->A -> B -> .... ->A +> A -> B -> .... ->A tip: @@ -10,13 +10,11 @@ tip: 解决方法:当一个对象已经实例化完毕了,还未初始化的时候,将它注入到它所依赖的已经实例好的对象(提前暴露对象),使得它所依赖的对象是个完整对象(实例化+初始化),然后再将这个完整对象注入给它。 -
- -### 简单工程(Spring-version-5.3.18) +## 简单工程(Spring-version-5.3.18) 我们就用下面两个类进行实践,多个类间依赖也是如此。 -A类 +A 类 ```java package cn.demo1; @@ -31,7 +29,7 @@ public class A { } ``` -B类 +B 类 ```java package cn.demo1; @@ -46,7 +44,7 @@ public class B { } ``` -配置文件test1.xml +配置文件 test1.xml ```xml @@ -63,24 +61,24 @@ public class B { ``` -DefaultSingletonBeanRegistry类中的几个特别重要的属性 +DefaultSingletonBeanRegistry 类中的几个特别重要的属性 ```java -//一级缓存 存放完整Bean对象(实例化+初始化) +// 一级缓存 存放完整Bean对象(实例化+初始化) private final Map singletonObjects = new ConcurrentHashMap<>(256); -//三级缓存 存放一个lambda表达式 +// 三级缓存 存放一个lambda表达式 private final Map> singletonFactories = new HashMap<>(16); -//二级缓存 存放一个半成品bean对象(只是实例化还未初始化),提前暴露 +// 二级缓存 存放一个半成品bean对象(只是实例化还未初始化),提前暴露 private final Map earlySingletonObjects = new ConcurrentHashMap<>(16); ``` > 循环依赖问题应该是出现属性填充的时候 -doCreateBean这个方法 +doCreateBean 这个方法 -> 可以参照[createBeanInstance](https://github.com/yang520-bye/source-code-hunter/blob/main/docs/Spring/clazz/Spring-beanFactory.md#createbeaninstance)查看Spring是怎么实例化的 +> 可以参照 [createBeanInstance](/docs/Spring/clazz/Spring-beanFactory.md#createbeaninstance) 查看 Spring 是怎么实例化的 ```java protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) @@ -91,7 +89,7 @@ protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { - //就只是bean的实例化 + // 就只是bean的实例化 instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); @@ -99,13 +97,13 @@ protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } - - //一般为true + + // 一般为true boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName)); - //....省略部分 + // ....省略部分 if (earlySingletonExposure) { - - //这里是将一段lambda放入三级缓存中,可以看见bean填充属性之前会将三级缓存创建好,它传入了一个还未初始化的bean + + // 这里是将一段lambda放入三级缓存中,可以看见bean填充属性之前会将三级缓存创建好,它传入了一个还未初始化的bean addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; @@ -121,40 +119,40 @@ protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable addSingletonFactory ```java -//其中singletonFactory是一个lambda表达式 +// 其中singletonFactory是一个lambda表达式 protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { - //如果我们一级缓存中不存在这个叫beanName的bean + // 如果我们一级缓存中不存在这个叫beanName的bean if (!this.singletonObjects.containsKey(beanName)) { - //放入三级缓存中 + // 放入三级缓存中 this.singletonFactories.put(beanName, singletonFactory); - //把二级缓存中叫beanName的半成品bean删除 + // 把二级缓存中叫beanName的半成品bean删除 this.earlySingletonObjects.remove(beanName); - //标记当前注册的bean + // 标记当前注册的bean this.registeredSingletons.add(beanName); } } } ``` -lambda所执行的方法 +lambda 所执行的方法 ```java protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; - //普通bean是进不来的 + // 普通bean是进不来的 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) { exposedObject = bp.getEarlyBeanReference(exposedObject, beanName); } } - //直接返回传进来的bean,返回的是一个还未初始化的bean,是提前暴露的 + // 直接返回传进来的bean,返回的是一个还未初始化的bean,是提前暴露的 return exposedObject; } ``` -populateBean中有调用了applyPropertyValues这个方法具体详情请点击这里[applyProertyValues](https://github.com/doocs/source-code-hunter/blob/main/docs/Spring/clazz/Spring-beanFactory.md#applypropertyvalues) +populateBean 中有调用了 applyPropertyValues 这个方法具体详情请点击这里 [applyProertyValues](/docs/Spring/clazz/Spring-beanFactory.md#applypropertyvalues) ```java protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { @@ -167,88 +165,88 @@ protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrap deepCopy.add(pv); } else { - //属性名字 + // 属性名字 String propertyName = pv.getName(); //当你引用另一个bean的时候,会把它封装成RuntimeBeanReference这个对象,便于操作 Object originalValue = pv.getValue(); - //这里是解析的工作,也就是会产生循环依赖产生的地方 + // 这里是解析的工作,也就是会产生循环依赖产生的地方 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); - //省略.... + // 省略.... } } ``` -applyPropertyValues中有个重要的方法调用,省略无关代码 +applyPropertyValues 中有个重要的方法调用,省略无关代码 ```java -//我们当前需要要的就是 +// 我们当前需要要的就是 public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { - //当前bean的属性值的类型正是这个 + // 当前bean的属性值的类型正是这个 if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } - //省略... + // 省略... } ``` -resolveReferance中有一段代码 +resolveReferance 中有一段代码 ```java -//这个方法会调用getBean +// 这个方法会调用getBean @Nullable private Object resolveReference(Object argName, RuntimeBeanReference ref) { - //省略... - - //上面一般进不去,直接看这个重点 + // 省略... + + // 上面一般进不去,直接看这个重点 resolvedName = String.valueOf(doEvaluate(ref.getBeanName())); - //获取所依赖的bean + // 获取所依赖的bean bean = this.beanFactory.getBean(resolvedName); - - //省略... - + + // 省略... + } ``` -getBean从而到这个doGetBean方法,其他代码不多说,最主要是下面这个 +getBean 从而到这个 doGetBean 方法,其他代码不多说,最主要是下面这个 -其中有一段代码,首先它会尝试从缓存中获取到bean,如果获取不到就创建这个bean +其中有一段代码,首先它会尝试从缓存中获取到 bean,如果获取不到就创建这个 bean ```java Object sharedInstance = getSingleton(beanName); ``` -> 获取缓存bean的顺序是,先从一级缓存中取,若不存在,从二级缓存中取,若还是不存在,则从三级缓存中取 +> 获取缓存 bean 的顺序是,先从一级缓存中取,若不存在,从二级缓存中取,若还是不存在,则从三级缓存中取 ```java @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { - //一级缓存中是否存在 + // 一级缓存中是否存在 Object singletonObject = this.singletonObjects.get(beanName); - //如果想要获取的bean正在创建中且无一级缓存 + // 如果想要获取的bean正在创建中且无一级缓存 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { - //尝试二级缓存 + // 尝试二级缓存 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { synchronized (this.singletonObjects) { singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { - //获取二级缓存 + // 获取二级缓存 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null) { - //获取三级缓存 + // 获取三级缓存 ObjectFactory singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { - //调用三级缓存,这个地方就会调用我们的lambda表达式了 + // 调用三级缓存,这个地方就会调用我们的lambda表达式了 /** *() -> getEarlyBeanReference(beanName, mbd, bean) *这里就是我们解决办法的地方,因为所有普通的bean会首先提前进行三级缓存 *所以这里会获取到还未初始化的bean,从而赋值到所依赖当前singletonObject对象的bean */ singletonObject = singletonFactory.getObject(); - //放入二级缓存中 + // 放入二级缓存中 this.earlySingletonObjects.put(beanName, singletonObject); - //三级缓存中移除当前beanName的lambda表达式 + // 三级缓存中移除当前beanName的lambda表达式 this.singletonFactories.remove(beanName); } } @@ -256,18 +254,15 @@ protected Object getSingleton(String beanName, boolean allowEarlyReference) { } } } - //完整对象或者还未初始化的对象 + // 完整对象或者还未初始化的对象 return singletonObject; } ``` 最后经历这个就获取到一个半成品对象所依赖的一个完整对象,然后再将完整对象注入半成品对象中。 -
- -### 历程 +## 历程 -Tip: +> 该历程仅代表当前这个项目工程 ->该历程仅代表当前这个项目工程 - +![image](/images/spring/循环依赖.png)