spring系列5-IOC的三级缓存

目录

1. 前言

2. 如何写demo

3. demo

4. 分析demo


 

1. 前言

在博客《spring系列3-IOC的实现》的第3节通过两张流程图大致梳理了IOC主要逻辑,值得关注的是3处红色标注的各级缓存放入处

考虑一下常见问题,加深对IOC三级缓存的理解:

问题1:IOC是如何解决循环依赖的?

比较浅地回答:通过缓存。在对象已实例化,但属性未装配(populate)前,将早期bean放入缓存中,使得递归解决属性注入时,依赖早期bean的其它bean能够拿到早期bean的引用。

问题2:IOC解决循环依赖为什么需要3级缓存,只用1级缓存行不行?只用2级缓存行不行?

根据博客:https://my.oschina.net/u/4340310/blog/4332450

(1)1级缓存不够,原因:如果只有1级缓存,存放了已实例化但未装配属性的bean,值=null的属性可能引发空指针,所以至少需要2级,一级存放完全可用的bean、二级存放早期的bean。

(2)2级缓存不够,参考别人的博文没想明白,只知道与代理、SmartInstantiationAwareBeanPostProcessor接口有关。还是自己动手写用例,通过debug来理解。

2. 如何写demo

研究SmartInstantiationAwareBeanPostProcessor接口

《spring系列3-IOC的实现》第3节的第2张流程图的三级缓存放入处代码如下:

spring系列5-IOC的三级缓存_第1张图片

在《spring系列3-IOC的实现》第3节的第1张流程图的二级缓存放入处回调getEarlyBeanReference(...)方法,方法内部会调用SmartInstantiationAwareBeanPostProcessor接口的getEarlyBeanReference(...)方法,而上述接口的直接实现类只有2个:AbstractAutoProxyCreator(可能返回代理)、InstantiationAwareBeanPostProcessorAdapter(直接返回bean)。

spring系列5-IOC的三级缓存_第2张图片

既然要理解第3级缓存对于代理情况的作用,那就基于AbstractAutoProxyCreator写用例。

ps:如果对advice陌生,可以了解一下《spring系列4-AOP的实现》

3. demo

demo很简单,就是Mother类、Child类相互依赖:

//Child类依赖Mother类
public class Child {

	private Mother mother;

	public Mother getMother() {
		return mother;
	}

	public void setMother(Mother mother) {
		this.mother = mother;
	}

}

//Mother类依赖Child类
public class Mother {

	private Child child;

	public Child getChild() {
		return child;
	}

	public void setChild(Child child) {
		this.child = child;
	}

}

//起床BPP处理器,只对Mother类返回advice
public class GetUpPostProcessor extends AbstractAutoProxyCreator {

	@Override
	protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource customTargetSource) throws BeansException {
		if (beanClass.equals(Mother.class)) {
			return new Object[]{new GetUpAdvice()};
		} else {
			return null;
		}
	}

	static class GetUpAdvice implements AfterReturningAdvice {
		@Override
		public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
			System.out.println("Hurry up! You will be late!");
		}
	}
}

public class MainTest {

	@Test
	public void test() {
		BeanFactory bf = new XmlBeanFactory(new ClassPathResource("mytest/ioc/circularrefercence/beanFactoryTest.xml"));
		BeanPostProcessor postProcessor = new GetUpPostProcessor();
		((XmlBeanFactory) bf).addBeanPostProcessor(postProcessor);
		Mother mother = (Mother) bf.getBean("mother");
		System.out.println(mother);
	}
}



	
		
	

	
		
	

4. 分析demo

获取bean的流程如下:

spring系列5-IOC的三级缓存_第3张图片

 

继续回答问题2(2):2级缓存不够,原因:2th级缓存用于存放proxy或未注入属性的bean,3th缓存用于存放生产2th缓存的工厂。

是否可以将3th缓存生产的内容直接放入2th缓存,不用3th缓存记录工厂呢?我想应该是不行的,工厂生产的proxy无法装配属性,调用populateBean方法会错误吧。

 

你可能感兴趣的:(spring源码阅读,java,spring,ioc)