天天看点

spring三级缓存解决循环依赖Spring三级缓存解决循环依赖

Spring三级缓存解决循环依赖

Spring中Bean的创建过程(生命周期)

Spring的refresh()方法 把扫描XML和注解的Bean解析成BeanDefintion并注册到beanFactory,再注册一些Bean处理器后再调用finishBeanFactoryInitialization(beanFactory)创建单例Bean,步骤如下:

  1. 实例化(掉用构造函数创建一个为填充任何属性的Bean)
  2. 属性装配(@Autowried 依赖注入)
  3. 初始华(aop增强)
  4. 销毁

Spring的三级缓存作用和getSingleton()

//一级缓存,存放完整的Bean
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 
	// 二级缓存,存放未填充属性的代理Bean或无代理Bean
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); 
	// 三级缓存,存放所有单例Bean的工厂
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); 

	//获取单例Bean方法
	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) {
						//若对象被代理此步骤获取代理后的Bean
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
           

为什么不是二层呢?

首先第三级是产生Bean的工厂,我们不能删除,第一层存放的是完整的Bean我们也不能删除,只能删掉第二层了。在无AOP的情况的循环依赖还是可以解决的。

A(B)

B(A)

但是在有AOP的情况下,同时有代理类和非代理(A和AP),该怎么处理呢?这里有一个方案:ObjectFactory直接产生代理类AP而不是A,再进行依赖注入,但是这更改了Bean的生命周期。这是不希望看到的(或者这里还有其他缺点或致命缺陷我没有想到)。所以使用了三层缓存,在未发生循环依赖时不打乱Bean的生命周期,增加一层缓存用于存放代理类,也使得三个缓存的分工明确。但是在有aop的情况下,打破生命周期还是无法避免的。

AOP增强的循环依赖会打破Bean的生命周期

假设类A和B都用了AOP增强,那么Spring会为其创建动态代理类AP和BP。这里大家思考一下,A依赖B还是BP呢?没错,A中需要的是增强后的BP,B同理依赖增强后的AP,用如下方式表示:

A(BP)

B(AP)

可以看到A这边的AP(A代理类)创建被提前了,而B这边的生命周期是没有问题的,这是使用AOP且出现循环依赖的情况时无法避免的。