BeanDefinition冻结相关源码解析

        今天讲解下beanFactory.freezeConfiguration();也就是常说的冻结Bean定义。

        首先我们来看下一个有趣的现象:

        第一个类UserTest:

                没什么特别的只是有个构造方法,方便我们看它实例化

第二个类:

 这个类就有点意思了,首先我获取了UserTest的BD,然后调用beanFactory.freezeConfiguration();

最后设置下懒依赖为true,楼主目的很简单,就是为了测试我们在冻结后,是否可以更改BeanDefinition的属性;我们来看结果:

 结果发现:即使设置了懒依赖,仍然进行了实例化操作,这里楼主但是就推断BeanDefinition确实被冻结了。

而后当楼主在测试其他属性时就发现不对劲了,看代码:

 这里楼主想将Scope设置为原型模式,按照上面理解,应该也不生效,但是结果如下:

 

 我们发现多例模式竟然生效了,这就非常奇怪,为什么设置懒加载不生效,但是多例生效。

下面进入源码环节:

首先直接跳到

 refresh()方法下的invokeBeanFactoryPostProcessors(beanFactory);来进行查看

这里楼主分两步来进行调试,第一步我们看一下我们设置Bean定义为懒加载时为什么不生效,断点位置如下:

 此时我们查看两个BeanFactory的属性

 

 第一个就是BeanDefinitionMap,我们发现经过invokeBeanFactoryPostProcessors(beanFactory);方法后,我们即使冻结Bean定义,我们的懒加载也被正确设置为了true,那么按理说应该不会被实例化啊,与我们结果不符合啊,别急我们再看另外一个属性:

看我们的mergedBeanDefinitions的属性,发现它的懒加载为null,这才是我们想要的效果,没错懒加载为null,这个就是我们为什么第一个测试,懒加载设置后,并没有生效,因为spring是按照这个来进行实例化的,请注意绿色框框,后面有用,翻译过来就是是否过期,后面会解释,大家大概记住,如果为true,这个合并Bean定义代表已经过时,spring会重新合并。

下面对比实验开始,我来看相同断点下,Scope的情况:

 

 同样于懒加载一样,我们的Scope也正确被修改,看另外一个mergedBeanDefinitions

 可以发现毫无区别,那么是什么导致后面差异,一个生效一个未生效

继续调试:下面截图不太好截图,大概给大家说下,大家最好鼠标跟着点进去,就是refresh()方法内的实例化方法,遍历调用getBean

我这里直接说了,到我们红框这一步,RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);这一步我们实际获取的BD都是合并后的,也就是我们未修改的(我们修改的BeanDefinitionMap里面的),原因如下:

大家看到了吧,只要stale属性为false,我们都会获取合并后的,所以我们修改的BD时无效的,这里可以看出我们冻结时有效果的,继续看:

 注意看绿色框处,bd定义不能为抽象的,bd定义必须是单例,bd定义不是懒加载,才可以进入getBean(),注意了,我们此时的BD是合并后的哦,也就是没被修改的,所以我们设置的懒加载无效的,可以进入(这里就是为什么懒加载设置后无作用的原因,本质上我们只是改了BD而不是合并后的BD,所以改了没作用),同样我们修改成多例也是无效的,所以两个步骤都可以同时进入getBean()流程,这里可能有人要问了,那么为什么从结果看我们修改的多例生效了呢,下面就是解释:

在doGetBean()我们发现了多例生效的玄机:

 没错代码到红框处,获取出来的居然是被更改为多例的BD,这里有人就蒙蔽了,为什么前面getMergedLocalBeanDefinition(beanName)获取的是未修改的,这里获取的是修改过的呢?答案在绿框处,来看绿框做了啥

 令人震惊有没有,它将我们合并Bean定义设置为过期了,所以在下面我们getMergedLocalBeanDefinition(beanName)获取的实际上通过BeanDefinitionMap里面被修改过的重新生成的,这里大家就发现了,我们设置的多例生效了,实际上我们懒加载也生效了,但是由于跳过了判断懒加载的条件,所以即使懒加载生效了,也仍然不起作用。到这里流程解释得差不多了,但是统观全局,我们发现stale这个属性非常重要,就应因为他为false时,我们得懒加载和多例在geetBean()之前,都是未被修改的,总结下冻结确实有作用,当仅限于getBean之前。

 而我们如果不加beanFactory.freezeConfiguration();那么在invokeBeanFactoryPostProcessors(beanFactory);之后该属性实际上是true,原因就在invokeBeanFactoryPostProcessors(beanFactory);方法里面的最后一行

 

 我们看下冻结的代码:

 全文完~~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值