Spring Singleton Bean 三级缓存

spring getBean的三级缓存有点绕,但理清楚了,就会发现也挺简单的。

一、循环依赖

循环依赖有多种情况,以下整理的三种:

1、构造方法互相依赖

例如ServiceA的构造方法中依赖了ServiceB, Service的构造方法中依赖了ServiceA

public class ServiceA {
    private ServiceB serviceB;
	public ServiceA(ServiceB serviceB){
		this.serviceB = serviceB;
	}
}

public class ServiceB {
    private ServiceA serviceA;
	public ServiceB(ServiceA serviceA){
		this.serviceA = serviceA;
	}
}

2、属性互相依赖

例如ServiceA的field或者setter方法依赖ServiceB, 同时ServiceB也如此依赖ServiceA

public class ServiceA {
    @Autowired
    private ServiceB serviceB;
}

public class ServiceB {
    @Autowired
    private ServiceA serviceA;
}

3、构造方法依赖&属性依赖

例如:
例如ServiceA的构造方法中依赖了ServiceB
ServiceB的field或者setter方法依赖ServiceA

public class ServiceA {
    private ServiceB serviceB;
	public ServiceA(ServiceB serviceB){
		this.serviceB = serviceB;
	}
}

public class ServiceB {
    @Autowired
    private ServiceA serviceA;
}

第1种情况(构造方法互相依赖)Spring也无解,会抛出BeanCreationException, 异常信息:“Circular depends-on relationship between ‘serviceA’ and ‘serviceB’”

1、2两个情况都是spring可以处理的。

二、Spring循环依赖的理论依据

Spring循环依赖的理论依据其实是Java基于引用传递,当我们获取到对象的引用时,对象的field或者或属性是可以延后设置的。
Spring单例对象的初始化其实可以分为三步:(实例化、填充属性、初始化)

createBeanInstance ## 实例化
		↓
populateBean ## 填充属性
		↓
initializeBean ## 初始化
  • createBeanInstance
    实例化,实际上就是调用对应的构造方法构造对象,此时只是调用了构造方法,spring xml中指定的property并没有进行赋值
  • populate
    populateBean,填充属性,这步对spring xml中指定的property进行填充
  • initializeBean
    调用spring xml中指定的init方法,或者AfterPropertiesSet方法

三、三级缓存

对于单例对象来说,在Spring的整个容器的生命周期内,有且只存在一个对象,这个对象存在Cache中,Spring大量运用了Cache的手段,在循环依赖问题的解决过程中甚至使用了“三级缓存”。

“三级缓存”主要是指:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	...
	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

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

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
	...
}

从字面意思来说:
singletonObjects指单例对象的cache;
earlySingletonObjects指提前曝光的单例对象的cache;
singletonFactories指单例对象工厂的cache;
以上三个cache构成了三级缓存,Spring就用这三级缓存巧妙的解决了循环依赖问题。

可以理解为三个桶,例如:
在这里插入图片描述
假设:A和B的field互相依赖
1、先尝试获取A,A在所有缓存中都没有;
2、创建A的实例,并封装成一个ObjectFactory放入三级缓存;
3、填充A属性field B;
4、尝试获取B,B在所有缓存中都没有;
5、创建B的实例,并封装成一个ObjectFactory放入三级缓存;
6、填充B属性field a;
7、先尝试获取A,A在三级缓存中存在,获取三级缓存中的ObjectFactory对象返回A,并将A放入二级缓存,从三级缓存中删除
8、将A赋值给B.a
9、初始化B
10、将B加入一级缓存,并从二级、三级缓存中删除
11、返回B
12、将B赋值给A.b
13、初始化A
14、将A加入一级缓存,并从二级、三级缓存中删除
15、返回A

流程示意图如下:
在这里插入图片描述

下面将利用到缓存的核心代码贴出来,不相关的代码去掉:
AbstractBeanFactory#doGetBean

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 从缓存中获取Bean, #@see DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference)
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			...
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			...
			try {
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				...
				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 创建Bean,加入三级缓存,填充属性,初始化都在这个方法中, @see AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				...
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}
		...
		return (T) bean;
	}

从缓存中获取Bean的代码逻辑: DefaultSingletonBeanRegistry#getSingleton(String, boolean )

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

**创建Bean的代码逻辑:**AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			//创建实例
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//创建实例
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		...

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			...
			// 添加三级缓存
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// 填充属性
			populateBean(beanName, mbd, instanceWrapper);
			// 初始化, 执行BeanPostProcessor
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			...
		}


		...
		return exposedObject;
	}

上面的代码就是spring IoC Bean三级缓存的执行逻辑。

附一张debug的调用链:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值