前言:
在这之前Spring已经通过document对象解析出BeanDefinition实例
以下就是将BeanDefinition注册进容器的步骤
在DefaultBeanDefinitionDocumentReader 类中的 processBeanDefinition()方法完成了对BeanDefinition的注册
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { |
方法中的Registry参数在跟进参数后可以发现返回的是AbstractBeanDefinitionReader中的Registry变量,该Registry变量便是BeanDefinitionRegistry的实例。
|
随后我们查看AbstractBeanDefinitionReader的构造函数发现Registry变量是通过构造函数的参数传递的
并且在构造函数中的IF函数中判断了传递过来的Registry是否为ResourceLoader实例,如果是则把Registry强转ResourceLoader并且传递到成员变量(resourceLoader)上。如果不是则给成员变量(resourceLoader)传递新的PathMatchingResourcePatternResolver对象。
PathMatchingResourcePatternResolver:支持多配置文件的资源加载器 |
其中的 BeanDefinitionReaderUtils 调用了 registerBeanDefinition() 方法来将我们的 BeanDefinition 注册到 DefaultListableBeanFactory 中的 beanDefinitionMap 中。
接下来我们进入 registerBeanDefinition() 方法。
|
我们可以通过Debug的方式跟进到该方法,此时我们会发现registry参数是自身(DefaultListableBeanFactory)传递过来的,前面我们说到DefaultListableBeanFactory类实现了BeanDefinitionRegistry接口,然后在现在这个方法中将自己当作Registry使用。也就是比较经典的委派模式
|
|
随后我们跟进registerBeanDefinition方法。方法中首先会进行校验,然后会从容器中获取BeanDefinition实例,看看是否存在。
如果实例已经注册过了便会根据容器的配置来决定是否是否支持覆盖原先的实例,随后对权限等等进行校验,如果最后都通过了则最终更新beanDefinitionMap
如果实例没有注册过,则进入else代码块中:首先判断容器是否已经开始创建Bean实例,随后用synchronized锁住beanDefinitionMap,此时Map中已经存有Bean实例了,在此对它进行新增添加,后更新注册表中的beanDefinitionNams(将新增的和原先的添加进去)。最后removeManualSingletonName(beanName)再对已经注册的单例Bean名字列表进行更新。
在removeManualSingletonName()方法中只调用了方法updateManualSingletonNames |