Spring-源码-doCreateBean方法解读

一、先看下代码大致结构

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

	BeanWrapper instanceWrapper = null;
	
	// 步骤1
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	
	// 步骤2
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		addSingletonFactory(beanName, new ObjectFactory<Object>() {
			@Override
			public Object getObject() throws BeansException {
				return getEarlyBeanReference(beanName, mbd, bean);
			}
		});
	}

	// 步骤3
	Object exposedObject = bean;
	populateBean(beanName, mbd, instanceWrapper);
	
	//步骤4
	if (exposedObject != null) {
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}

	// 步骤5
	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
		}
	}
	return exposedObject;
}

上面是精简doCreateBean方法,这五个步骤是我认为相对比较重要的,下面说下这个五个步骤完成功能

1、拿到Bean的普通实例,这里的普通实例是相对AOP代理的那种Bean而言的。普通bean大部分都是通过反射拿到构造方法创建实例对象

2、创建这个Bean的ObjectFactory的对象,并且把他加到第三级缓存中,主要用来解决循环依赖

3、给普通实例Bean填充属性,比如Bean里面有属性带了@Autowired,就是给里面的属性赋值

4、执行Bean的初始化的前置回调方法初始化回调方法初始化的后置回调方法,这里有个点需要知道,AOP代理的Bean大部分都是通过后置回调方法创建的

5、从一级或者二级缓存中获取Bean的实例,不从三级缓存中取

下面结合Bean的创建说下上面五参与创建Bean的流程:

二、创建非AOP代理的Bean,比如没有被切面拦截的Service,或者没有加@Transactional注解的Bean

1、通过步骤1创建Bean的实例
2、执行步骤2将Bean加到三级缓存中,三级缓存主要是解决AOP代理Bean被依赖的问题,所以步骤2在这没有作用
3、完成这个普通Bean里面的依赖属性,比如带有@Autowired属性赋值,比如带有@Value属性赋值

4、因为不是AOP处理的Bean,所以步骤4没有做用什么

5、步骤5从一、二级缓存没有拿到数据,所以这一步也没什么作用,最后返回步骤1创建的实例对象

总结:参与Bean的实例化也就步骤1,步骤3

二、创建AOP代理的Bean,没有循环依赖的情况

1、通过步骤1创建Bean的实例

2、执行步骤2将Bean加到三级缓存中,这里不涉及循环依赖,所以步骤2没有用

3、完成这个普通Bean里面的依赖属性

4、通过SmartInstantiationAwareBeanPostProcessor类型的后置处理器,调用postProcessAfterInitialization方法创建AOP代理的Bean

5、步骤5从一、二级缓存没有拿到数据,没什么作用

总结:最后返回4中创建的代理Bean,那么有人会问步骤1创建的普通实例Bean,就没用了吗,其实在步骤4创建代理Bean的时候,要用到步骤1创建的Bean,以Spring的JDK动态代理来说,创建的代理对象需要目标对象的实例对象,在执行invoke方法时,调用"目标方法"需要传"目标对象实例"的

三、创建非AOP代理的Bean,有循环依赖,A依赖B,B依赖A,A和B都是非AOP代理的Bean

假设A先实例化

1、A->步骤1,创建A的实例
2、A->步骤2,创建A的ObjectFactory的对象,并且把他加到第三级缓存中,后面会用到
3、A->步骤3,完成A实例里面的依赖属性,因为依赖B,但是B还没有实例化,这个会去实例化B

4、B->步骤1,创建B的实例
5、B->步骤2,创建B的ObjectFactory的对象,并且加到第三级缓存中
6、B->步骤3,填充B的属性,然后找依赖的A,发现缓存中只有一个ObjectFactory对象,通过ObjectFactory的getObject来得到A的实例对象,A是非AOP,getObject产生的实例对象和步骤1产生的普通实例是同一个实例。
7、B->步骤4,因为B非AOP代理对象,所以步骤四没有实质作用。
8、B->步骤5,没有实质作用,返回实例好的B,注意这里的B属性赋值也完成,最后存到一级缓存中。

9、A->步骤4,因为A是非AOP代理对象,所以步骤四没有实质作用。
10、A->步骤5,前面实例化B的时候,在执行节点6,拿到A在三级缓存的ObjectFactory,调用了getObject方法,把A又实例化了一次,但是因为A是非AOP代理,所以产生的实例和步骤1得到的普通实例,是一个实例,然后再把A存到了二级缓存,当执行到步骤5的时候,发现二级缓存中已经有A的实例,取出A的实例直接返回,注意因为是非AOP的Bean,所以ObjectFactory的getObject得到的时候存入二级缓存对象和节点1创建的实例对象是同一个对象。

总结:最后将实例A存到一次缓存中,至此实例化A和实例化B已经完成,实例对象都是在步骤1完成。提前引用彼此的实例对象地址,然后通过滞后性完成里面的属性填充。

四、创建AOP代理的Bean,有循环依赖,A依赖B,B依赖A,A是被AOP代理,B不是。

假设A先实例化。其实A是AOP代理和B是AOP代理产生的B一个道理

1、A->步骤1,创建A的实例
2、A->步骤2,创建A的ObjectFactory的对象,并且把他加到第三级缓存中,后面会用到
3、A->步骤3,完成A实例里面的依赖属性,因为依赖B,但是B还没有实例化,这个会去实例化B

4、B->步骤1,创建B的实例
5、B->步骤2,创建B的ObjectFactory的对象,并且加到第三级缓存中
6、B->步骤3,填充B的属性,然后找依赖的A,发现缓存中只有一个ObjectFactory对象,通过ObjectFactory的getObject来得到A的代理对象,注意getObject产生的是A的代理Bean,和前面节点1产生的普通实例不是一个实例,最后存到二级缓存中。可以发现B里面属性A,填进去的是A的代理Bean。
7、B->步骤4,因为B非AOP代理对象,所以步骤四没有实质作用。
8、B->步骤5,没有实质作用,返回实例好的B,注意这里的B属性赋值也完成,最后存到一级缓存中。

9、A->步骤4,A是AOP代理对象,所以步骤4会去创建A的代理对象。但是此时A的代理对象已经被B调用getObject产生了,而且还引用了,所以步骤4会先从缓存中判断是否已经创建了A的代理对象,如果创建了就不会再去创建,返回创建好的。
10、A->步骤5,前面实例化B的时候,在节点6,已经把A存到了二级缓存,所以从二级缓存取出A的实例返回,其实二级缓存对象和节点1创建的实例对象不一样的,一个是普通对象,一个是代理对象。

注意:创建依赖的AOP代理Bean和创建依赖的非AOP代理主要区别是在:节点6、节点9、节点10,中间利用了一个earlyProxyReferences来处理是否还要创建AOP代理对象,如果创建过就把BeanName会存到earlyProxyReferences里面去。

有时间可以参考这篇文章写的非常好:https://cloud.tencent.com/developer/article/1497692

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信仰_273993243

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值