1、将BeanDefinition注册进IoC容器部分的源码分析文档

2、完善readme
pull/2/head
AmyliaY 6 years ago
parent f411f58217
commit 6efbcb2f23

@ -7,11 +7,13 @@
[![issues](https://badgen.net/github/open-issues/doocs/source-code-hunter)](https://github.com/doocs/source-code-hunter/issues)
[![PRs Welcome](https://badgen.net/badge/PRs/welcome/green)](http://makeapullrequest.com)
阅读互联网公司主流框架源码,目前开放的有 Spring 系列框架、Mybatis 框架、Netty 框架,欢迎各位大佬加入我们,开拓新的领地。本项目主要用于记录框架源码的阅读经验及解析,抽空更新中...
阅读互联网公司主流框架源码,目前开放的有 Spring 系列框架、Mybatis 框架、Netty 框架,欢迎各位大佬加入我们,开拓新的领地。本项目主要用于记录框架源码的阅读经验、个人理解及解析,抽空更新中...
## spring系列
### IoC容器
- [BeanDefinition的资源定位过程](/docs/Spring/IoC/一、BeanDefinition的资源定位过程.md)
- [将bean解析封装成BeanDefinition](/docs/Spring/IoC/二、将bean解析封装成BeanDefinition.md)
- [将BeanDefinition注册进IoC容器](/docs/Spring/IoC/三、将BeanDefinition注册进IoC容器.md)
### AOP
### SpringMVC
@ -24,5 +26,12 @@
## Netty
## 学习心得
### 初级开发者应该从源码中学习什么?
### 编码规范
### 设计模式
## License
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.

@ -0,0 +1,115 @@
这篇文章分享一下spring IoC容器初始化第三部分的代码也就是将前面解析得到的BeanDefinition注册进IoC容器其实就是存入一个ConcurrentHashMap<String, BeanDefinition>中。
PS可以结合我GitHub上对spring框架源码的翻译注解一起看会更有助于各位同学理解地址
spring-beans https://github.com/AmyliaY/spring-beans-reading
spring-context https://github.com/AmyliaY/spring-context-reading
## 1、回过头看一下前面在DefaultBeanDefinitionDocumentReader中实现的processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)方法
```java
// 解析Bean定义资源Document对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder是对BeanDefinition的封装即BeanDefinition的封装类
// 对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 对bdHolder进行包装处理
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
/**
*
* 向Spring IoC容器注册解析BeanDefinition这是BeanDefinition向IoC容器注册的入口
*
*/
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 在完成向Spring IOC容器注册解析得到的Bean定义之后发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
```
## 2、BeanDefinitionReaderUtils的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法
```java
// 将解析的BeanDefinitionHold注册到容器中
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 获取解析的BeanDefinition的名称
String beanName = definitionHolder.getBeanName();
/**
*
* 开始向IOC容器注册BeanDefinition
*
*/
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 如果解析的BeanDefinition有别名向容器为其注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}
```
## 3、BeanDefinitionRegistry中的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法在DefaultListableBeanFactory实现类中的具体实现
```java
// 向IoC容器注册解析的BeanDefinito
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 校验解析的BeanDefiniton
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 注册的过程中需要线程同步,以保证数据的一致性
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 检查是否有同名的BeanDefinition已经在IOC容器中注册如果已经注册
// 并且不允许覆盖已注册的BeanDefinition则抛出注册失败异常
// allowBeanDefinitionOverriding默认为true
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {// 如果允许覆盖则同名的Bean后注册的覆盖先注册的
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {// IOC容器中没有已经注册同名的Bean按正常注册流程注册
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 重置所有已经注册过的BeanDefinition的缓存
resetBeanDefinition(beanName);
}
```
## 最后看一下spring的IoC容器在代码中最直接的体现
```java
// 存储注册信息的BeanDefinition集合也就是所谓的IoC容器
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
```
Loading…
Cancel
Save