spring 单例的循环依赖

现象

  • 两个类都是spring的单例类,两个类里面有一个成员变量,变量都是对方。
  @Component
public class BeanA
{
	@Resource
	private BeanB beanB;
	
}

@Component
class BeanB
{
	@Resource
	private BeanA beanA;
	
}

这个问题不是什么复杂的问题。正常思路是这样的。

BeanA a = new BeanA();
BeanB b = new BeanB();

a.setBeanB(b);
b.setBeanA(a);

spring 创建对象

spring的思路是这样子的,这个就出现了循环依赖的问题

public static BeanA createA() {

	BeanA beanA = new BeanA();
	BeanB b = createB();
	beanA.setBeanB(b);
	return beanA;
}

public static BeanB createB() {
	BeanB beanB = new BeanB();
	BeanA a = createA();
	beanB.setBeanA(a);
	return beanB;
}

spring的理念是,只要你创建一个对象,那么这个对象中的需要自动注入的属性就要即时注入,如果没有就创建这个属性,或者报错。

  • spring的解决方式(引入缓存)伪代码

	private static Map<String,Object> cacheObjects = new HashMap<>();

	public static BeanA createA() {
		// 先从缓存中获取
		BeanA beanA = (BeanA) cacheObjects.get("beanA");
		if (beanA != null){
			return beanA;
		}
		beanA = new BeanA();
		cacheObjects.put("beanA",beanA);
		BeanB b = createB();
		beanA.setBeanB(b);
		return beanA;
	}

	public static BeanB createB() {
		// 先从缓存中获取
		BeanB beanB = (BeanB) cacheObjects.get("beanB");
		if (beanB != null){
			return beanB;
		}
		beanB = new BeanB();
		cacheObjects.put("beanB",beanB);
		BeanA a = createA();
		beanB.setBeanA(a);
		return beanB;
	}

源码解读

流程图

在这里插入图片描述

  • 先尝试从缓存中拿取实例
// 从缓存中拿取实例
		Object sharedInstance = getSingleton(beanName);

缓存容器

/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

从缓存中先尝试获取

....
	Object singletonObject = null;
		// 从三级缓存中获取实例
	ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
	if (singletonFactory != null) {
		singletonObject = singletonFactory.getObject();
	}

	return singletonObject;
		....

如果对象不存在创建一个对象

	// 创建实例
	instanceWrapper = createBeanInstance(beanName, mbd, args);

创建对象之后加入缓存,注意这个对象是一个空的对象。

this.singletonFactories.put(beanName, singletonFactory);

之后来进行属性注入

		// 获取有@AutoWired 注解的字段和方法
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			// 进行设置值
			metadata.inject(bean, beanName, pvs);
		}
	// 获取依赖注入的值
	value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

如果它是一个对象类型的数据,最终触发getBean操作

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
		throws BeansException {

	return beanFactory.getBean(beanName);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值