码迷,mamicode.com
首页 > 编程语言 > 详细

Spring: BeanDefinition的注册(源码跟进)

时间:2021-02-19 13:17:42      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:abstract   utils   ioc   parse   except   cep   res   single   资源加载   

前言:

在这之前Spring已经通过document对象解析出BeanDefinition实例

以下就是将BeanDefinition注册进容器的步骤

 

DefaultBeanDefinitionDocumentReader 类中的 processBeanDefinition()方法完成了对BeanDefinition的注册

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
  //BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
  //对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//向SpringIOC容器注册解析得到的BeanDefinition,这是BeanDefinition向IOC容器注册的入口
      //传递的参数bdHolder为BeanDefinition的包装类,另一个参数为registry实例。

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name ‘" +
bdHolder.getBeanName() + "‘", ele, ex);
}
//在完成BeanDefinition注册之后,往容器发送注册完成的事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

方法中的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

Spring: BeanDefinition的注册(源码跟进)

标签:abstract   utils   ioc   parse   except   cep   res   single   资源加载   

原文地址:https://www.cnblogs.com/zcl1116/p/14409507.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!