前言
上一篇我们整理了IoC相关的几个类体系架构,本篇从一小段代码开始Debug,看Spring具体的实现。
源码分析
从容器获取一个单例的Bean:
public static void main(String[] args) {
// 入口,加载xml配置,刷新容器,见#1
ApplicationContext context = new ClassPathXmlApplicationContext("spring/spring-ioc.xml");
// 单例下这个getBean()实际上是从缓存中获取的
StudentB studentB1 = (StudentB) context.getBean("studentB");
StudentB studentB2 = (StudentB) context.getBean("studentB");
// 输出的结果是一样的
System.out.println("studentB1: " + studentB1);
System.out.println("studentB2: " + studentB2);
}
调用方法:org.springframework.context.support.AbstractApplicationContext#refresh
// #1 完成IoC容器的创建及初始化
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 预刷新处理,刷新上下文,设置启动数据,初始化环境数据
prepareRefresh();
// 重点,刷新初始化容器,完成BeanDefinition注册,见#2
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 对IoC容器进行一些预处理,设置一些公共属性
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 对BeanDefinition进行处理
invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化消息源
initMessageSource();
// 初始化应用事件广播器
initApplicationEventMulticaster();
// 初始化一些特殊的bean
onRefresh();
// 检测监听器并注册
registerListeners();
// 重点, 实例化所有剩余的单例bean(非懒加载方式)
// Bean的IoC、DI都是发生在此步骤
finishBeanFactoryInitialization(beanFactory);
// 完成刷新,发布对应的事件
finishRefresh();
}
catch (BeansException ex) {
// 省略代码...
}
finally {
// 省略代码...
}
}
}
注册BeanDefinition
调用方法:org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
// #2 刷新容器
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 主要是通过该方法完成IoC容器的刷新,见#3
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 省略代码...
return beanFactory;
}
调用方法:org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
// #3 刷新IoC容器
protected final void refreshBeanFactory() throws BeansException {
// 如果已经有IoC容器,则销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建默认的IoC容器 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 设置工厂的属性,是否允许BeanDefinition覆盖和是否允许循环依赖
customizeBeanFactory(beanFactory);
// 加载BeanDefinition,这个抽象方法,具体的实现让具体的子类完成,见#4
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
// 省略代码...
}
}
调用方法:org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions
// #4 读取xml类型的资源文件
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 获取资源路径
Resource[] configResources = getConfigResources();
if (configResources != null) {
// XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
reader.loadBeanDefinitions(configResources);
}
// 获取资源路径,我们这里是:spring/spring-ioc.xml
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
// 见#5
reader.loadBeanDefinitions(configLocations);
}
}
调用方法:org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions
// #5 经过一系列的调用,包装,在这里开始解析xml文件获得BeanDefinition
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 省略代码...
try {
// 将资源文件转为流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// do开头的方法是真正执行过程,开始解析,见#6
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
// 省略代码...
}
// 省略代码...
}
调用方法:org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions
// #6 开始解析加载
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 通过DOM4J加载解析XML文件,最终形成Document对象
Document doc = doLoadDocument(inputSource, resource);
// 通过对Document对象的操作,完成BeanDefinition的加载和注册工作,见#7
return registerBeanDefinitions(doc, resource);
}
// 省略代码...
}
调用方法:org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinition
// #7 又经过一系列的处理,会在添加到一个map中
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
// 省略代码...
// 如果是重复的BeanDefinition的一系列处理判断
}
else {
// 不是第一个BeanDefinition的处理逻辑
// 但是我们这里没有标记,所以还是会走下面逻辑
if (hasBeanCreationStarted()) {
// 省略代码...
}
// 如果是第一个BeanDefinition的处理逻辑
else {
// 会存进一个map中,beanName是key,beanDefinition是value
// beanName:就是bean的名称,我们这里是studentB
// beanDefinition:储存着一个bean的详细信息,如下图
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 省略代码...
}
BeanDefinition中的bean信息数据结构
创建Bean
前面已经完成了Bean信息的加载,接下来看下Bean是如何创建的,这里有个经典的循环依赖问题,也通过源码看Spring是如何处理的。
还是调用这个方法:org.springframework.context.support.AbstractApplicationContext#refresh
// 完成IoC容器的创建及初始化
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 省略代码...
try {
// 省略代码...
// 重点, 实例化所有剩余的单例bean(非懒加载方式)
// Bean的IoC、DI都是发生在此步骤
finishBeanFactoryInitialization(beanFactory);
}
catch (BeansException ex) {
// 省略代码...
}
finally {
// 省略代码...
}
}
}
调用方法:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 获取bean名称
final String beanName = transformedBeanName(name);
Object bean;
// 从缓存或单例工厂中获取单例bean,见##1
Object sharedInstance = getSingleton(beanName);
//如果获取到单例bean,则走下面代码
if (sharedInstance != null && args == null) {
// 如果取出来的Bean实例是FactoryBean的Bean实例
// 则需要从FactoryBean实例中产生一个对象实例。
// FactoryBean可以对某类复杂Bean生成对象,BeanFactory则是任意对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果没有获取到单例bean,则走下面代码
else {
// 如果是原型模式的Bean发生循环引用,不处理,直接抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 省略代码...
try {
// 获取要实例化的bean的BeanDefinition对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 省略代码...
// 如果是单例的Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建单例Bean的主要方法,见##2
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 省略代码...
}
});
// 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是原型的Bean
else if (mbd.isPrototype()) {
// 省略代码...
}
// 处理request或session的Bean
else {
// 省略代码...
}
}
// 省略代码...
}
// 省略代码...
return (T) bean;
}
调用方法:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
// ##1,一级没有去二级拿,二级没有去三级拿,三级拿完移除并添加到二级中
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存中获取单例对象
Object singletonObject = this.singletonObjects.get(beanName);
// isSingletonCurrentlyInCreation() :
// 判断当前单例bean是否正在创建中,也就是没有初始化完成
// 比如A的构造器依赖了B对象所以得先去创建B对象,或者在A的populateBean过程中依赖了B对象,得先去创建B对象
// 这时的A就是处于创建中的状态。
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存中获取单例bean
singletonObject = this.earlySingletonObjects.get(beanName);
// allowEarlyReference():
// 是否允许从singletonFactories中通过getObject拿到对象
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存中获取单例bean
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 通过单例工厂获取单例bean
singletonObject = singletonFactory.getObject();
// 从三级缓存移动到了二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
调用方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
// ##2 完成Bean实例的创建(实例化、填充属性、初始化)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 省略代码...
// bean初始化第一步:默认调用无参构造实例化Bean
// 构造参数依赖注入,就是发生在这一步
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 实例化后的Bean对象
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 省略代码...
// 如果是单例且允许循环依赖且该Bean还在创建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 如果需要提前暴露单例Bean,则将该Bean放入三级缓存中
if (earlySingletonExposure) {
// 将刚创建的bean放入三级缓存中singleFactories(key是beanName,value是FactoryBean)
addSingletonFactory(beanName,
() -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// bean初始化第二步:填充属性(DI发生在此步骤)
populateBean(beanName, mbd, instanceWrapper);
// bean初始化第三步:调用初始化方法,完成bean的初始化操作
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// 省略代码...
return exposedObject;
}
循环依赖
什么是循环依赖?
循环依赖就是循环引用,两个或多个bean相互之间的持有对方。例如A依赖B,而B又依赖A,最终形成闭环,并且只有单例Bean的循环依赖可以通过setter注入方式来解决,构造注入无法解决,其他类型的Bean更无法处理。
循环依赖处理
先看看一个Bean实例化的三个步骤:
- createBeanInstance 调用对象的构造方法实例化对象,是“残缺的”
- populateBean 对象属性填充
- initializeBean 对象初始化
循环依赖发生在第2步,因此我们也在第2步来处理,处理的策略是利用缓存。例如对象A依赖对象B,对象B又依赖对象A,那么当对象A实例化后进行属性填充,需要填充对象B,这时又去实例化B,填充B对象的属性发现要实例化A,但此时Spring会先去缓存中查找,而缓存又分为三级缓存。
一级缓存:singletonObject
,缓存单例Bean
二级缓存:earlySingletonObjects
,缓存实例化后的Bean,提前曝光
三级缓存:singletonFactories
,缓存的是单例对象工厂,对Bean做beanPostProcessor后置处理,处理后在添加到二级缓存中并同时删除三级缓存中的数据,它才是真正处理循环依赖的。
在看完org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean就会明白为什么只能处理单例的setter循环依赖,因为Bean实例化第一步就是调用构造器来实例化对象,而field初始化是可以延迟的。
参考资料
请你相信我所说的都是错的