From 6efbcb2f23dcdac1aed26ce042f5249bac56ca7e Mon Sep 17 00:00:00 2001
From: AmyliaY <471816751@qq.com>
Date: Fri, 1 Nov 2019 23:01:08 +0800
Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=B0=86BeanDefinition=E6=B3=A8?=
=?UTF-8?q?=E5=86=8C=E8=BF=9BIoC=E5=AE=B9=E5=99=A8=E9=83=A8=E5=88=86?=
=?UTF-8?q?=E7=9A=84=E6=BA=90=E7=A0=81=E5=88=86=E6=9E=90=E6=96=87=E6=A1=A3?=
=?UTF-8?q?=202=E3=80=81=E5=AE=8C=E5=96=84readme?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 13 +-
...、BeanDefinition的资源定位过程.md} | 0
...、将BeanDefinition注册进IoC容器.md | 115 ++++++++++++++++++
...将bean解析封装成BeanDefinition.md} | 0
4 files changed, 126 insertions(+), 2 deletions(-)
rename docs/Spring/IoC/{BeanDefinition的资源定位过程.md => 一、BeanDefinition的资源定位过程.md} (100%)
create mode 100644 docs/Spring/IoC/三、将BeanDefinition注册进IoC容器.md
rename docs/Spring/IoC/{将bean解析封装成BeanDefinition.md => 二、将bean解析封装成BeanDefinition.md} (100%)
diff --git a/README.md b/README.md
index ca660e0..f3d7d12 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,13 @@
[](https://github.com/doocs/source-code-hunter/issues)
[](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

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
\ No newline at end of file
diff --git a/docs/Spring/IoC/BeanDefinition的资源定位过程.md b/docs/Spring/IoC/一、BeanDefinition的资源定位过程.md
similarity index 100%
rename from docs/Spring/IoC/BeanDefinition的资源定位过程.md
rename to docs/Spring/IoC/一、BeanDefinition的资源定位过程.md
diff --git a/docs/Spring/IoC/三、将BeanDefinition注册进IoC容器.md b/docs/Spring/IoC/三、将BeanDefinition注册进IoC容器.md
new file mode 100644
index 0000000..69716d9
--- /dev/null
+++ b/docs/Spring/IoC/三、将BeanDefinition注册进IoC容器.md
@@ -0,0 +1,115 @@
+这篇文章分享一下spring IoC容器初始化第三部分的代码,也就是将前面解析得到的BeanDefinition注册进IoC容器,其实就是存入一个ConcurrentHashMap中。
+ (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对象中元素的解析由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 beanDefinitionMap = new ConcurrentHashMap(64);
+```
+
+
diff --git a/docs/Spring/IoC/将bean解析封装成BeanDefinition.md b/docs/Spring/IoC/二、将bean解析封装成BeanDefinition.md
similarity index 100%
rename from docs/Spring/IoC/将bean解析封装成BeanDefinition.md
rename to docs/Spring/IoC/二、将bean解析封装成BeanDefinition.md