Skip to content

Commit

Permalink
有代理对象的循环依赖
Browse files Browse the repository at this point in the history
  • Loading branch information
DerekYRC committed Jan 30, 2021
1 parent 6eba0ad commit bfd342b
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 11 deletions.
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,9 @@ A依赖B,B又依赖A,循环依赖。容器加载时会执行依赖流程:

下一节填坑。

## 解决循环依赖问题(二):有代理对象
> 分支:circular-reference-with-proxy-bean



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
* @author derekyi
Expand All @@ -22,8 +24,24 @@ public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPos

private DefaultListableBeanFactory beanFactory;

private Set<Object> earlyProxyReferences = new HashSet<>();

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (!earlyProxyReferences.contains(beanName)) {
return wrapIfNecessary(bean, beanName);
}

return bean;
}

@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
earlyProxyReferences.add(beanName);
return wrapIfNecessary(bean, beanName);
}

protected Object wrapIfNecessary(Object bean, String beanName) {
//避免死循环
if (isInfrastructureClass(bean.getClass())) {
return bean;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/springframework/beans/factory/ObjectFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.springframework.beans.factory;

import org.springframework.beans.BeansException;

/**
* @author derekyi
* @date 2021/1/30
*/
public interface ObjectFactory<T> {

T getObject() throws BeansException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,17 @@ public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
*/
PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName)
throws BeansException;

/**
* 提前暴露bean
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.*;
import org.springframework.core.convert.ConversionService;

Expand Down Expand Up @@ -70,7 +71,13 @@ protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {

//为解决循环依赖问题,将实例化后的bean放进缓存中提前暴露
if (beanDefinition.isSingleton()) {
earlySingletonObjects.put(beanName, bean);
Object finalBean = bean;
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, beanDefinition, finalBean);
}
});
}

//实例化bean之后执行
Expand All @@ -92,11 +99,27 @@ protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

if (beanDefinition.isSingleton()) {
addSingleton(beanName, bean);
//如果有代理对象,此处获取代理对象
Object exposedObject = getSingleton(beanName);
addSingleton(beanName, exposedObject);
}
return bean;
}

protected Object getEarlyBeanReference(String beanName, BeanDefinition beanDefinition, Object bean) {
Object exposedObject = bean;
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
exposedObject = ((InstantiationAwareBeanPostProcessor) bp).getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return exposedObject;
}
}
}

return exposedObject;
}

/**
* bean实例化后执行,如果返回false,不执行后续设置属性的逻辑
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.SingletonBeanRegistry;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

Expand All @@ -15,26 +15,44 @@
*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

//一级缓存
private Map<String, Object> singletonObjects = new HashMap<>();

protected Map<String, Object> earlySingletonObjects = new HashMap<>();
//二级缓存
private Map<String, Object> earlySingletonObjects = new HashMap<>();

//三级缓存
private Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>();

private final Map<String, DisposableBean> disposableBeans = new HashMap<>();

@Override
public Object getSingleton(String beanName) {
Object bean = singletonObjects.get(beanName);
if (bean == null) {
bean = earlySingletonObjects.get(beanName);
Object singletonObject = singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//从三级缓存放进二级缓存
earlySingletonObjects.put(beanName, singletonObject);
singletonFactories.remove(beanName);
}
}
}
return bean;
return singletonObject;
}

@Override
public void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
singletonFactories.put(beanName, singletonFactory);
}

public void registerDisposableBean(String beanName, DisposableBean bean) {
disposableBeans.put(beanName, bean);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ public void testCircularReference() throws Exception {
A a = applicationContext.getBean("a", A.class);
B b = applicationContext.getBean("b", B.class);

//增加二级缓存不能解决有代理对象时的循环依赖。
//a被代理,放进二级缓存earlySingletonObjects中的是实例化后的A,而放进一级缓存singletonObjects中的是被代理后的A,实例化b时从earlySingletonObjects获取a,所以b.getA() != a
assertThat(b.getA() != a).isTrue();
assertThat(b.getA() == a).isTrue();
}
}

0 comments on commit bfd342b

Please sign in to comment.