diff --git a/README.md b/README.md
index af8032b..47c1d13 100644
--- a/README.md
+++ b/README.md
@@ -1,54 +1,86 @@
# mini-spring
[![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/DerekYRC/mini-spring)
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+[![Stars](https://img.shields.io/github/stars/DerekYRC/mini-spring)](https://img.shields.io/github/stars/DerekYRC/mini-spring)
+[![Forks](https://img.shields.io/github/forks/DerekYRC/mini-spring)](https://img.shields.io/github/forks/DerekYRC/mini-spring)
-## About
-* [中文版](./README_CN.md)
-
-The **mini-spring** is a simplified version of the Spring framework that will help you quickly get familiar with the Spring source code and grasp the core principles of Spring. The core logic of Spring is extracted, the code is extremely simplified, and the core functions of Spring, such as IoC and AOP, resource loaders, event listeners, type conversion, container extension points, bean life cycle and scope, and application context, are retained.
-
-If this project can help you, please give a **STAR, thank you!!!**
-
-## Contents
-#### Basics
-* [IoC](#Ioc)
- * [Implement a simple container](#实现一个简单的容器)
- * [BeanDefinition and BeanDefinitionRegistry](#BeanDefinition和BeanDefinitionRegistry)
- * [Bean Instantiation Strategy](#Bean实例化策略InstantiationStrategy)
- * [Populate bean with property values](#为bean填充属性)
- * [Populate bean with bean](#为bean注入bean)
- * [Resource and ResourceLoader](#资源和资源加载器)
- * [Define the bean in the XML file](#在xml文件中定义bean)
- * [Container extension mechanism:BeanFactoryPostProcess and BeanPostProcessor](#容器扩展机制BeanFactoryPostProcess和BeanPostProcessor)
- * [ApplicationContext](#应用上下文ApplicationContext)
- * [Init method and destroy method of bean](#bean的初始化和销毁方法)
- * [Aware interface](#Aware接口)
- * [Bean scope, added prototype support](#bean作用域,增加prototype的支持)
- * [FactoryBean](#FactoryBean)
- * [Event and event listener](#容器事件和事件监听器)
-* [AOP](#AOP)
- * [Pointcut expression](#切点表达式)
- * [JDK-based dynamic proxy](#基于JDK的动态代理)
- * [CGLIB-based dynamic proxy](#基于CGLIB的动态代理)
- * [AOP ProxyFactory](#AOP代理工厂ProxyFactory)
- * [Common Advice: BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice](#几种常用的Advice)
- * [PointcutAdvisor:A combination of Pointcut and Advice](#PointcutAdvisor:Pointcut和Advice的组合)
- * [Dynamic proxies are integrated into the bean lifecycle](#动态代理融入bean生命周期)
+**[English](./README_en.md) | 简体中文**
+
+**姊妹版:**[**mini-spring-cloud**](https://github.com/DerekYRC/mini-spring-cloud) **(简化版的spring cloud框架)**
+
+## 关于
+
+**mini-spring**是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,**代码极度简化,保留spring的核心功能**,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展点、bean生命周期和作用域、应用上下文等核心功能。
+
+如果本项目能帮助到你,请给个**STAR,谢谢!!!**
+
+## 功能
+#### 基础篇
+* [IoC](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基础篇IoC)
+ * [实现一个简单的容器](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#最简单的bean容器)
+ * [BeanDefinition和BeanDefinitionRegistry](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#BeanDefinition和BeanDefinitionRegistry)
+ * [Bean实例化策略InstantiationStrategy](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#Bean实例化策略InstantiationStrategy)
+ * [为bean填充属性](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#为bean填充属性)
+ * [为bean注入bean](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#为bean注入bean)
+ * [资源和资源加载器](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#资源和资源加载器)
+ * [在xml文件中定义bean](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#在xml文件中定义bean)
+ * [容器扩展机制BeanFactoryPostProcess和BeanPostProcessor](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#BeanFactoryPostProcess和BeanPostProcessor)
+ * [应用上下文ApplicationContext](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#应用上下文ApplicationContext)
+ * [bean的初始化和销毁方法](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#bean的初始化和销毁方法)
+ * [Aware接口](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#Aware接口)
+ * [bean作用域,增加prototype的支持](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#bean作用域增加prototype的支持)
+ * [FactoryBean](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#FactoryBean)
+ * [容器事件和事件监听器](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#容器事件和事件监听器)
+* [AOP](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基础篇AOP)
+ * [切点表达式](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#切点表达式)
+ * [基于JDK的动态代理](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基于JDK的动态代理)
+ * [基于CGLIB的动态代理](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#基于CGLIB的动态代理)
+ * [AOP代理工厂ProxyFactory](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#AOP代理工厂)
+ * [几种常用的Advice: BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#几种常用的AdviceBeforeAdviceAfterAdviceAfterReturningAdviceThrowsAdvice)
+ * [PointcutAdvisor:Pointcut和Advice的组合](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#pointcutadvisorpointcut和advice的组合)
+ * [动态代理融入bean生命周期](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#动态代理融入bean生命周期)
+#### 扩展篇
+* [PropertyPlaceholderConfigurer](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#propertyplaceholderconfigurer)
+* [包扫描](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#包扫描)
+* [@Value注解](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#value注解)
+* [基于注解@Autowired的依赖注入](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#autowired注解)
+* [类型转换(一)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#类型转换一)
+* [类型转换(二)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#类型转换二)
+
+#### 高级篇
+* [解决循环依赖问题(一):没有代理对象](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#解决循环依赖问题一没有代理对象)
+* [解决循环依赖问题(二):有代理对象](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#解决循环依赖问题二有代理对象)
+
+#### 其他
+* [没有为代理bean设置属性(discovered and fixed by kerwin89)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#bug-fix没有为代理bean设置属性discovered-and-fixed-by-kerwin89)
+* [支持懒加载和多切面增强(by zqczgl)](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md#支持懒加载和多切面增强by-zqczgl)
+
+## 使用方法
+阅读[changelog.md](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md)
+
+[视频教程(完整版)](https://www.bilibili.com/video/BV1nb4y1A7YJ)
+
+## 提问
+[**点此提问**](https://github.com/DerekYRC/mini-spring/issues/4)
+
+## 贡献
+欢迎Pull Request
+
+## 关于我
+[**点此了解**](https://github.com/DerekYRC)
+
+手机/微信:**15521077528** 邮箱:**15521077528@163.com**
-#### Expanding
-* [PropertyPlaceholderConfigurer](#PropertyPlaceholderConfigurer)
-* [Type conversion](#类型转换)
-* [Package scan](#包扫描)
-* [Autowired annotation](#基于注解的依赖注入Autowired)
+## Star History
-#### Advanced
-* [Solve the problem of circular dependencies](#解决循环依赖问题)
+[![Star History Chart](https://api.star-history.com/svg?repos=DerekYRC/mini-spring&type=Date)](https://star-history.com/#DerekYRC/mini-spring&Date)
-## Usage
-Each function point corresponds to a branch. Switch to the branch corresponding to the function point to see the new function. The incremental change point is described in the [changelog.md](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md) file.
+## 版权说明
+未取得本人书面许可,不得将该项目用于商业用途
-## Reference
+## 参考
- [《Spring源码深度解析》](https://book.douban.com/subject/25866350/)
+- [《Spring 源码解析》](http://svip.iocoder.cn/categories/Spring)
- [《精通Spring 4.x》](https://book.douban.com/subject/26952826/)
-- [tiny-spring](https://github.com/code4craft/tiny-spring)
+- [《tiny-spring》](https://github.com/code4craft/tiny-spring)
diff --git a/README_CN.md b/README_CN.md
deleted file mode 100644
index 42c344b..0000000
--- a/README_CN.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# mini-spring
-[![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/DerekYRC/mini-spring)
-[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
-
-## 关于
-* [English version](./README.md)
-
-**mini-spring**是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,代码极度简化,保留spring的核心功能,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展点、bean生命周期和作用域、应用上下文等核心功能。
-
-如果本项目能帮助到你,请给个**STAR,谢谢!!!**
-
-## 功能
-#### 基础篇
-* [IoC](#Ioc)
- * [实现一个简单的容器](#实现一个简单的容器)
- * [BeanDefinition和BeanDefinitionRegistry](#BeanDefinition和BeanDefinitionRegistry)
- * [Bean实例化策略InstantiationStrategy](#Bean实例化策略InstantiationStrategy)
- * [为bean填充属性](#为bean填充属性)
- * [为bean注入bean](#为bean注入bean)
- * [资源和资源加载器](#资源和资源加载器)
- * [在xml文件中定义bean](#在xml文件中定义bean)
- * [容器扩展机制BeanFactoryPostProcess和BeanPostProcessor](#容器扩展机制BeanFactoryPostProcess和BeanPostProcessor)
- * [应用上下文ApplicationContext](#应用上下文ApplicationContext)
- * [bean的初始化和销毁方法](#bean的初始化和销毁方法)
- * [Aware接口](#Aware接口)
- * [bean作用域,增加prototype的支持](#bean作用域,增加prototype的支持)
- * [FactoryBean](#FactoryBean)
- * [容器事件和事件监听器](#容器事件和事件监听器)
-* [AOP](#AOP)
- * [切点表达式](#切点表达式)
- * [基于JDK的动态代理](#基于JDK的动态代理)
- * [基于CGLIB的动态代理](#基于CGLIB的动态代理)
- * [AOP代理工厂ProxyFactory](#AOP代理工厂ProxyFactory)
- * [几种常用的Advice: BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice](#几种常用的Advice)
- * [PointcutAdvisor:Pointcut和Advice的组合](#PointcutAdvisor:Pointcut和Advice的组合)
- * [动态代理融入bean生命周期](#动态代理融入bean生命周期)
-
-
-#### 扩展篇
-* [PropertyPlaceholderConfigurer](#PropertyPlaceholderConfigurer)
-* [类型转换](#类型转换)
-* [包扫描](#包扫描)
-* [基于注解的依赖注入Autowired](#基于注解的依赖注入Autowired)
-
-#### 高级篇
-* [解决循环依赖问题](#解决循环依赖问题)
-
-## 使用方法
-每个功能点对应一个分支,切换到功能点对应的分支了解新增的功能,增量改动点在[changelog.md](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md)文件中描述。
-
-## 参考
-- [《Spring源码深度解析》](https://book.douban.com/subject/25866350/)
-- [《精通Spring 4.x》](https://book.douban.com/subject/26952826/)
-- [tiny-spring](https://github.com/code4craft/tiny-spring)
diff --git a/README_en.md b/README_en.md
new file mode 100644
index 0000000..79175b2
--- /dev/null
+++ b/README_en.md
@@ -0,0 +1,71 @@
+# mini-spring
+[![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/DerekYRC/mini-spring)
+[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+[![Stars](https://img.shields.io/github/stars/DerekYRC/mini-spring)](https://img.shields.io/github/stars/DerekYRC/mini-spring)
+[![Forks](https://img.shields.io/github/forks/DerekYRC/mini-spring)](https://img.shields.io/github/forks/DerekYRC/mini-spring)
+
+**English | [简体中文](./README.md)**
+
+[**mini-spring-cloud**](https://github.com/DerekYRC/mini-spring-cloud) **(simplified version of the Spring Cloud framework)**
+
+## About
+
+The **mini-spring** is a simplified version of the Spring framework that will help you quickly get familiar with the Spring source code and grasp the core principles of Spring. The core logic of Spring is extracted, the code is extremely simplified, and the core functions of Spring, such as IoC and AOP, resource loaders, event listeners, type conversion, container extension points, bean life cycle and scope, and application context, are retained.
+
+If this project can help you, please **STAR the project, thank you!!!**
+
+## Contents
+#### Basics
+* [IoC](#Ioc)
+ * [Implement a simple container](#实现一个简单的容器)
+ * [BeanDefinition and BeanDefinitionRegistry](#BeanDefinition和BeanDefinitionRegistry)
+ * [Bean Instantiation Strategy](#Bean实例化策略InstantiationStrategy)
+ * [Populate bean with property values](#为bean填充属性)
+ * [Populate bean with bean](#为bean注入bean)
+ * [Resource and ResourceLoader](#资源和资源加载器)
+ * [Define the bean in the XML file](#在xml文件中定义bean)
+ * [Container extension mechanism:BeanFactoryPostProcess and BeanPostProcessor](#容器扩展机制BeanFactoryPostProcess和BeanPostProcessor)
+ * [ApplicationContext](#应用上下文ApplicationContext)
+ * [Init method and destroy method of bean](#bean的初始化和销毁方法)
+ * [Aware interface](#Aware接口)
+ * [Bean scope, added prototype support](#bean作用域,增加prototype的支持)
+ * [FactoryBean](#FactoryBean)
+ * [Event and event listener](#容器事件和事件监听器)
+* [AOP](#AOP)
+ * [Pointcut expression](#切点表达式)
+ * [JDK-based dynamic proxy](#基于JDK的动态代理)
+ * [CGLIB-based dynamic proxy](#基于CGLIB的动态代理)
+ * [AOP ProxyFactory](#AOP代理工厂ProxyFactory)
+ * [Common Advice: BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice](#几种常用的Advice)
+ * [PointcutAdvisor:A combination of Pointcut and Advice](#PointcutAdvisor:Pointcut和Advice的组合)
+ * [Dynamic proxies are integrated into the bean lifecycle](#动态代理融入bean生命周期)
+
+
+#### Expanding
+* [PropertyPlaceholderConfigurer](#PropertyPlaceholderConfigurer)
+* [Package scan](#包扫描)
+* [Value annotation](#Value)
+* [Autowired annotation](#Autowired)
+* [Type conversion(first part)](#类型转换一)
+* [Type conversion(second part)](#类型转换二)
+
+#### Advanced
+* [Solve the problem of circular dependencies(first part): without proxy bean](#解决循环依赖问题一)
+* [Solve the problem of circular dependencies(second part): with proxy bean](#解决循环依赖问题二)
+
+#### Bug fix
+* [populate proxy bean with property values(discovered and fixed by kerwin89)](#没有为代理bean设置属性)
+
+## Usage
+Each function point corresponds to a branch. Switch to the branch corresponding to the function point to see the new function. The incremental change point is described in the [changelog.md](https://github.com/DerekYRC/mini-spring/blob/main/changelog.md) file.
+
+## Contributing
+Any contributions you make are greatly appreciated.
+
+## Contact
+Please feel free to ask me any questions related to mini-spring and other technologies. My email is **15521077528@163.com**.
+
+## Reference
+- [《Spring源码深度解析》](https://book.douban.com/subject/25866350/)
+- [《精通Spring 4.x》](https://book.douban.com/subject/26952826/)
+- [tiny-spring](https://github.com/code4craft/tiny-spring)
diff --git a/assets/application-context-life-cycle.drawio b/assets/application-context-life-cycle.drawio
new file mode 100644
index 0000000..b6f4432
--- /dev/null
+++ b/assets/application-context-life-cycle.drawio
@@ -0,0 +1 @@
+7ZnbcpswEIafRpfpmJMQl2CTtDPJTDqetkluOopRgBYjV8ixnaevJCQDPiRup3Zd11dGv1Yg7e4nwRo4/fH8iuFJdkMTUgC7l8yBMwC2bfegLX6ksqgVy0JaSVmeaK0RhvkL0WJPq9M8IVXHkFNa8HzSFUe0LMmIdzTMGJ11zZ5o0X3qBKdkTRiOcLGufskTntUqsv1Gf0/yNDNPtmBQ94yxMdYrqTKc0FlLcmLg9BmlvL4az/ukkN4zfqnHXW7pXU6MkZLvMuDl68tt+uFj+HmYk/wxCL2H5NMF0nPjC7Ngkoj16yZlPKMpLXERN2rE6LRMiLxrT7Qam2tKJ0K0hPiNcL7QwcRTToWU8XGhe8k853dy+DtPt+5bPYO5vrNqLEyj5GzRGiSb9+2+ZphqmXHrXtKOq+iUjcgrrjHZhllK+Ct2Op+l31oP0DG4InRMxHyEASMF5vlzN6+wTs90addEUFzoIP5CQPV9n3Ex1U8CNizE/KMnKjzQDjX8MaWm46JSwQqFgYUm86ZTXKX6V92lmuDSaHc31yCGIIAA+SB2QRSBCBpDMfu2bUuuJ2LklfRrkkvmwyzLORlOsArUTGwx3USqOKPfSZ8WlKnRDrIfHQjlmvKiaOmJR1Di6rWa7N5AkPEeYZzMX42m2eGQptvsb4b2WbNZWFBrWWujcHt7SoDgTPQbpL5JtHNURNt7IjoiuByQp7zMeU7LU+XT7fJp99b5XNochE/zYnMGdCt4bwIKjwpQZ4+AXuIRp2xxSyt+y+iIVJVARh61lyCM1eErroP/AuXl0WpQRusou+igKNtnlLf5xt0RZf+oUHb3iPIKwx5AAUADEPsgGiiYPRC6ALlSCXoAwRPleHkEa45dd51jxz4ox96Z422+8Xbk2HKPCmTvkCBLWuMzyHDDu/WBQbbWfHqkIP8+kHBHII+LR7gnHh8Fjwq4GASxejGOAYrU6dqXhakTJW+l6uTAv111spx/hbzDH6H+jsR6R0Wsvydi5UerePMNfRAjEFqC05phcVaG6tAU6CIQDBTVfgfmutYcBfIickDgnSreK0Urb0NR+cBFq319GKkteyDLGTIBXBCiE42ps1K9gBuqF3+oeCGazb+Kqq/156wT/wQ=
\ No newline at end of file
diff --git a/assets/auto-proxy.drawio b/assets/auto-proxy.drawio
new file mode 100644
index 0000000..33bac5a
--- /dev/null
+++ b/assets/auto-proxy.drawio
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/assets/aware-interface.drawio b/assets/aware-interface.drawio
new file mode 100644
index 0000000..2d088c9
--- /dev/null
+++ b/assets/aware-interface.drawio
@@ -0,0 +1 @@
+7Ztfk6I4EMA/TR69kv/wiMrsbtXOlnvW3e3ey1WUDOYWCQdx1Pn0l2AQEERnSpASnySdAKE7v3SnE4EyXm0/RTBcPhMX+UAeulugTIAsy6ZpsR8u2e0lkmTKe4kXYVfIMsEMvyEhHArpGrsoLjSkhPgUh0XhggQBWtCCDEYR2RSbvRC/+NYQeqgkmC2gX5b+hV263EtN2cjknxH2lumbJV188QqmjcWXxEvokk1OpDhAGUeE0P3VajtGPtdeqpf9fU8nag8di1BAL7nh7Z+3qfflu/3nDCM8t2ztb/ePgSn6RnfpByOXfb8okoguiUcC6DuZdBSRdeAi/tQhK2VtvhISMqHEhP8iSnfCmHBNCRMt6coXtWiL6Q9++2+aKP3M1Uy24slJYZcWAhrtcjfx4s98XXZbUkrvK2tJKC4m62iBalSTjjYYeYjWtBPjmest9wJhg0+IrBDrD2sQIR9S/FocV1AMT+/QLrMguxBGfIdBxXNfob8WbwKy7rP+j14I00De1Pp/a5JWDOLEWDZrIJnhNqtkV574TZ4ShzBIZT+evwJHB5YOTAM4KhiNwEhPG7Le59vmxPuOpOKj4ZcNLj4eNktM0SyEiaE2bIopDqSYRuQXGhOfRMndiinPFV3n34R9Pyd3NWS6qvjWdHRXEJRqD0UUbWuteZjhBN1iflNFcZPNFZIuZMvcPJG2u7r9rQfQZ0A9C7TSKaDlhoAeIRhM0AsOMMUkuFc81SKeklzm89CmFT7TuOYB6EnwzgKqdwpQpUFAn+CCkmg3JTGdRmSB4pghwz3tE7CdxPeya6sXKB/QFSjLwzLKqtkqyvID5VO6US9E2egUymqDKB8xrAG2NDYnwDHAaJLArAFbBabKJdYQmPqdcnzgNo2YK0JmRW6VY+3B8SndaBdyLKmdAllrE2ROq/MAWa9wyI2B7FMyCH69ehB6u+3Udp/jcJYule6d4yPGPga2Xga7Uqc3xVhvCOM5wzjh1AGWk8TTDjBHiVMe83TWnQJ7lKs6lG+WrJKUfhD7EUCNCz2vdivHq8fuHBuf4+/Ot/FU+ab//jbwBmWDXs9cOWNlpjtjLqlgrMx2bZirUkFSp+Iko6EJlqcm2PrGNoBjAlti0+p+ymURkZ2ERmymNYE1SSZhozD37jcURha/GCnA0u51Nj5KTWptpiYrh2b9XmBAgh7NvlJFAqNSad1KYEhNZTCSIGnC846cYRXY5p1iqRylGfWKIKmpLGPlAFP7SWWd8zwLpdypmKipLfkvPN8PffyGA48nJhgW8IWiaBqRkI13jOIZoneK6aCURqzgtLHsQ6WZ67OI1wZVAh+Ihofg+tFwHYDdTf/X9boB52nyEzK2neYc7MSdWjxEfk8kzDf4BuxTl8TtC9aafmusJamk1EYdcFdWuXXR7lkHbHWK65utci0eKjPHxNrZT8CUeru4NSowbndxe2azvl9xtHUhxulhpY5wbDXE8QTHIYnh3EcijHYRR2h3p3CWnKxRkXpq2cnWbwT0K3hOqetu7qm22+2Gz+ddrIC5Z4GzefPd+J7s7b13N/70LvsF62W1JcDrOtnkQVd7w5THOIkRzUm7y2wJ0ArzX3yARmlzrVtp4dsehGtt5XsVZC894XpTZJvaDrLD0McLyI+bj1l7tKU5csuVdwqwfsFRVvVKq1xWzP4qmtTl/nGrOP8D
\ No newline at end of file
diff --git a/assets/chainProceed.png b/assets/chainProceed.png
new file mode 100644
index 0000000..bda72e3
Binary files /dev/null and b/assets/chainProceed.png differ
diff --git a/assets/init-and-destroy-method.drawio b/assets/init-and-destroy-method.drawio
new file mode 100644
index 0000000..dde0db2
--- /dev/null
+++ b/assets/init-and-destroy-method.drawio
@@ -0,0 +1 @@
+7Ztbs9o2EIB/jR7p4Lv8aINPkpkkQ8q0TfrSMVjHVmssaotw+fWVjIRtbC5JseEAT1gryUhafburFQBtMFu9S/159IkEKAZqP1gBbQhUVYXQZh9cst5KFAWqW0mY4kDICsEYb5AQ9oV0gQOUVRpSQmKK51XhlCQJmtKKzE9Tsqw2eyVx9VvnfohqgvHUj+vSP3BAo60UqlYhf49wGMlvVkwx45kvG4uZZJEfkGVJpHlAG6SE0O3TbDVAMV89uS7bfi8HancDS1FCz+mw+WszCj98cX4fY4QntmP8GfzWg2JsdC0njAI2f1EkKY1ISBI/9gqpm5JFEiD+1j4rFW0+EjJnQoUJ/0aUroUy/QUlTBTRWSxq0QrTr7z7L4YofSvVDFfizXlhLQsJTdelTrz4rVxXdMtLsl99lcTCZWSRTtGRpZG7zU9DRI+0E/uZr1vpC4QO3iEyQ2w8rEGKYp/i79V95YvtGe7aFRpkD0KJP6BQ8d7vfrwQ3wRUM2bjd18JW4Gyqs1/F0RW9LJcWQ5roMD5qqhkT6H4zN+Szf1Eyr5++gg8E9gmgBbwdOC6wDVlQzb6ctuSeDsQKd7bfsXm4vthGWGKxnM/V9SSmZjqRspoSv5BAxKTNO+tQXWimSafE47jkjwwEAx0MVe5uxsIkquHUopWR7W5s3CCbmnfJO3LwlgoppBFJUOh91vaAPaT6BOkniRauymi1ZaIdpGfDNErTjDFJLlXPvUqn2q/zueuTSd8ysDmCehB8E4Cat4UoFqLgL74U0rS9YhkdJSSKcoyhgx3tS/A8XLny57th0B551olyrCOsg47RVl9onxobfQzUbZuCmW9RZT3GDYAOxvDIfAs4A5zmA3g6ADqXGL3ATTvlOOdCxYc63qdY03tlGPjyfGhtTHO5FjRbwpko0uQOa3eE2SzIbbuGGSltqY3CvLPA2meCeRt8Wi2xOOE8ZgD5wHbywNjD0A3964Dnpi6U/L2sk6aee2sk6K9FfK6d6HWmcQa1yLWzIIJtt5nX7zPg5H22fx10wt7dYVeTl0lZRWqO6EupaKsQndH1bW3lhfTX+OKXdXAWi0ZWJ5jYAcVxwIeBI7CzOrW5LLQxsljHGZpIbCHuRG2KrZ3ezXg2vzB1YBt3Ks13ssxGg13AK3lGBt34vFbvYQkb9T6XgRnpSE10biK1jV5VtpKReRB0pAnEDnDOnDgnWKp7eULzYZ8YVvpwsb9pD+pPOE8z4BSvWZM1Nbl+geeuPdjvMFJyDMMDAv/laJ0lJI52+8YZWNEbxfTGpMNW+Agpr1aPrCB09bSCI1qPp4OvDSoCviJaLgPOoiGDwN4bmL/WqCqrTlPyH/r4jgy5+Dk7tTmIfKPRML8pq7HphqR4FGwNhpyFN1ifSI7eHEHfLOn3MPR7hkO2L4m11c75do8VGaOibVzXgBU3tLh9n9xvH+4tRow7vZwe+LW/cHjaPtMjJV+s9q74dhuieMhzuYk8ycxEmF0gDhC6zuFs+ZkrYbUU8dO9vhFwIMHz/LHfzeTezo6ym7D59MuVsD8YIEzbPFanRWLP6DkdaX/8Wjefw==
\ No newline at end of file
diff --git a/assets/populate-proxy-bean-with-property-values.drawio b/assets/populate-proxy-bean-with-property-values.drawio
new file mode 100644
index 0000000..7f3e4e9
--- /dev/null
+++ b/assets/populate-proxy-bean-with-property-values.drawio
@@ -0,0 +1 @@
+7Vxbd5s4EP41evQeczU8go3b7ml63M3Z3l72YKNgUoIoKLGdX7+SEDEX+ZIUMLX9ZBgkLGbmmxmNRgLK+GH9LnHj5Q3yYAjkobcGygTIsmwYJvmhlA2nKJqUUfwk8DJagXAbPENOHHLqY+DBtNQQIxTiIC4TFyiK4AKXaG6SoFW52R0Ky/8auz6sEW4Xblinfg08vMyohjza0t/DwF/m/yzp/Isf3Lwx/5J06XpoVSApDlDGCUI4u3pYj2FIuZfzJes33fH0ZWAJjPAxHZ7/e575Hz5bX24DGMxNS/vh/Tsw+NjwJv9g6JHv57cowUvko8gNnS3VTtBj5EH61iG527b5iFBMiBIh3kOMN1yY7iNGhLTEDyF/CtcB/ka7/6Xxu++FJ5M1fzO72eQ3EU42hU709nvx2bYbu8v71bnEGZeix2QB97Am1zY38SHe007O2lG+Ff6Ay+AdRA+QjIc0SGDo4uCprFcuV0//pd1WguSCC/EVAuXvfXLDR/5PQNZDMn77DhEOFEWt/3pE+YNByoRlkQaSEa+3D8mVz3/ZW9LYjXLat5uPwNGBqQNjBBwV2DawdUoxDEJchG6aCp7zF5GvK76rQM4GmpMr6rlVPqovq2WA4W3sMkGuiAkqK1qKE/QTjlGIEtZbMeS5ouv0m4MwLNA9DRqeynmRa78AYTl3YYLheq+0cwuocvRz+zfI71dbY/LSZlkwJDmtcQUxr4jvDMm86wwFDHpcJxS9rBOSXJF1ZnJ4r4q4X4bxdg2QWzIRNnSjCbwLogAHKLoQQHeJZ5jcG8t/br9NUfzjyfmyNm1jnkvziue6oit1Dy5kodQrD660CM+pu8Ao2cxQimcJWsA0JYChnnkKLIf5anJtXgSQX6xu1QoXkKwaXXpm6QrlnbxRjwzGR72CstoilCsY1gCZahsT4IyAPWFg1oClAkOlFHMIDP1McSwPyzjWjTqOFblTHGtXHO/ijXYkjiW1V0DWugQyRatzBbIhCK1bA/JqJt3jX+poejOe/60s081z+HmgXwaOKxh7G7D1OrCFPFVOCWO9JRjPCYwZTh1gOiyedoBhM6c8pumvMwWsUQasLPC8kt6p51UuA7FvAejoSM+rncrx6qk3D0bv08/Op/FM+aT/8zzwB3WBNieugrC2ojsgLqkkrK3suhCXkEH9yl2MWjKwbFHBBNYIOAawJGJWM5NLIiKLhUYaW3OYMCM8KtnebAHCNumFrQBTO1drXElMjvQOM5PmwJHhwHknaf4iSZZffX0lDfIl3Ks13j2/KeJbzMRe4VtqK6PBgqYJzUNSTKvAMs4Upkol7WgK0o5tZR2FDkTdC9IIReeJyn3O9KDTlXsVI7W15P+B5v/dMHgOIp8mKggs3DsMk1mCYqLvAUxvIT5TmA6q2YiRAKetZSOEYt6fVWwaqBJ4Q3Q8BM1Hx/sA2N/lgH2jbsF5GrTCxrLyHITF3KlJQ+bXRMZ0wW9APnWJvEuBtTE8NawlqcbUVh1wX2a9QmYcO+s1T4VrYYx+LaJ8jUCFLOyXoT5ZGsOkcx8S/pN21hQY0sVmLyRROUZr6QuxYZavM6OqwT2cjhz2CshmS0CeBGmMUnceQj4x8iDF0OZM0VkLm6Rhl1UWYk3bv9ZzWfOhHHYH8dkvP5sPu9sZ0WEny9F8YXMhSRIsGbQG6hCjQfTzyXddf7OeWd5NGt8KlvsuMZIWsubY7UgnK5wSlnv8OWtAQrb9hqha3zbyUujY/LaRfQrYZl26tSLcJjYvhbhAPVP7Wytc7TIVJZTwaetW+5KYErLm2Przk1nffaNuHLJWHIfBwqW7Q8akPVzjAnLrD88UwPoRledqQykLNL+nu9vlYejOYZjLUj6UmZQLH8AVpv+euNXYal+RRW9mT+SWC/wVWeiTbux90/S4Det9rHy7yUKzrlaSuJtCg5hGaOnuQE/TqskWtXKyw6EOcrkDucjG8NZ4cB9TG3cu6QLFEDhTYI+BOT3adyzRw/wxPew3dnmH3f6kAVdRrfqRhoJgT1T2U43xG1uzamtHSxpEfgjx8dtGWYBQklACyZ/Q3CrHPbU62d+yx24Y+BG5XhBxQCIrm4qBBByhxR88BJ7HrBsHGvkbzQbapCJ8niEsy12YNmxCAap7/odmXQFMgQJUzwZoTAHa2gsRJwgjvCEQvipAQQHUmgUQLHB1qgCiRc5qABGGQZzCw0bVTePs8KW7YE251hMrK3doZYUnC1zzmTtZc2w+U+8o5j5OoO3VWqbYjXDAps1sMl3fGior8fbehncogaVuZzrNrlQGiDCtt1UYIMxpC+zkOabJXpsKF+f/6yjfjauTLVK0BGq2+KgDQ2YrjA4wx2zNcUL3c293dRt014PJKKZNmmUlQWz6Y4zZsuWYrV9qdLWSXGdLm3a2H3xKX0dfMaJPS72M/DgImxUcZResDpTuTh3mbQRFSf01JDWrIdDKnYbEGEoHLUlT+brjFG90GeFBI5ZEcJiTsJ16SkvS1tlNrw4PLLpR4w+JDn4L1JXoQBGUMHQbHVxIMXAjmBasqgnbaafEdFuLaK/GNN93tflCR5JeBp5VwSEw3eL5Qs5LbQTPgtOdWimQ+S2BtpX5ZuGzQ4Pr4tFNtsSOhNFpxE1C7PMEbfUkGE2Q22zqJBhyuz0zPVvL2h49rzj/Aw==
\ No newline at end of file
diff --git a/assets/populate-proxy-bean-with-property-values.png b/assets/populate-proxy-bean-with-property-values.png
new file mode 100644
index 0000000..e27eac5
Binary files /dev/null and b/assets/populate-proxy-bean-with-property-values.png differ
diff --git a/assets/prototype-bean.drawio b/assets/prototype-bean.drawio
new file mode 100644
index 0000000..d93e34a
--- /dev/null
+++ b/assets/prototype-bean.drawio
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/changelog.md b/changelog.md
index 3b42239..801c78d 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,9 +1,9 @@
- # IOC
- ## 最简单的bean容器
- > 分支:simple-bean-container
+ # [基础篇:IoC](#基础篇IoC)
+ ## [最简单的bean容器](#最简单的bean容器)
+ > 代码分支:simple-bean-container
定义一个简单的bean容器BeanFactory,内部包含一个map用以保存bean,只有注册bean和获取bean两个方法
-```
+```java
public class BeanFactory {
private Map beanMap = new HashMap<>();
@@ -18,7 +18,7 @@ public class BeanFactory {
```
测试:
-```
+```java
public class SimpleBeanContainerTest {
@Test
@@ -39,20 +39,20 @@ public class SimpleBeanContainerTest {
}
```
-## BeanDefinition和BeanDefinitionRegistry
-> 分支:bean-definition-and-bean-definition-registry
+## [BeanDefinition和BeanDefinitionRegistry](#BeanDefinition和BeanDefinitionRegistry)
+> 代码分支:bean-definition-and-bean-definition-registry
主要增加如下类:
-- BeanDefinition,顾名思义,用于定义bean信息的类,包含bean的class类型、构造参数、属性值等信息,每个bean对应一个BeanDefinition的实例。简化BeanDefition仅包含bean的class类型。
-- BeanDefinitionRegistry,BeanDefinition注册表接口,定义注册BeanDefintion的方法。
+- BeanDefinition,顾名思义,用于定义bean信息的类,包含bean的class类型、构造参数、属性值等信息,每个bean对应一个BeanDefinition的实例。简化BeanDefinition仅包含bean的class类型。
+- BeanDefinitionRegistry,BeanDefinition注册表接口,定义注册BeanDefinition的方法。
- SingletonBeanRegistry及其实现类DefaultSingletonBeanRegistry,定义添加和获取单例bean的方法。
-bean容器作为BeanDefinitionRegistry和SingletonBeanRegistry的实现类,具备两者的能力。向bean容器中注册BeanDefintion后,使用bean时才会实例化。
+bean容器作为BeanDefinitionRegistry和SingletonBeanRegistry的实现类,具备两者的能力。向bean容器中注册BeanDefinition后,使用bean时才会实例化。
![](./assets/bean-definition-and-bean-definition-registry.png)
测试:
-```
+```java
public class BeanDefinitionAndBeanDefinitionRegistryTest {
@Test
@@ -74,8 +74,8 @@ class HelloService {
}
```
-## Bean实例化策略InstantiationStrategy
-> 分支:instantiation-strategy
+## [Bean实例化策略InstantiationStrategy](#Bean实例化策略InstantiationStrategy)
+> 代码分支:instantiation-strategy
现在bean是在AbstractAutowireCapableBeanFactory.doCreateBean方法中用beanClass.newInstance()来实例化,仅适用于bean有无参构造函数的情况。
@@ -85,13 +85,13 @@ class HelloService {
- SimpleInstantiationStrategy,使用bean的构造函数来实例化
- CglibSubclassingInstantiationStrategy,使用CGLIB动态生成子类
-## 为bean填充属性
-> 分支:populate-bean-with-property-values
+## [为bean填充属性](#为bean填充属性)
+> 代码分支:populate-bean-with-property-values
在BeanDefinition中增加和bean属性对应的PropertyValues,实例化bean之后,为bean填充属性(AbstractAutowireCapableBeanFactory#applyPropertyValues)。
测试:
-```
+```java
public class PopulateBeanWithPropertyValuesTest {
@Test
@@ -111,12 +111,12 @@ public class PopulateBeanWithPropertyValuesTest {
}
```
-## 为bean注入bean
-> 分支:populate-bean-with-bean
+## [为bean注入bean](#为bean注入bean)
+> 代码分支:populate-bean-with-bean
增加BeanReference类,包装一个bean对另一个bean的引用。实例化beanA后填充属性时,若PropertyValue#value为BeanReference,引用beanB,则先去实例化beanB。
由于不想增加代码的复杂度提高理解难度,暂时不支持循环依赖,后面会在高级篇中解决该问题。
-```
+```java
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
try {
for (PropertyValue propertyValue : beanDefinition.getPropertyValues().getPropertyValues()) {
@@ -138,7 +138,7 @@ protected void applyPropertyValues(String beanName, Object bean, BeanDefinition
```
测试:
-```
+```java
public class PopulateBeanWithPropertyValuesTest {
/**
@@ -176,8 +176,8 @@ public class PopulateBeanWithPropertyValuesTest {
}
```
-## 资源和资源加载器
-> 分支:resource-and-resource-loader
+## [资源和资源加载器](#资源和资源加载器)
+> 代码分支:resource-and-resource-loader
Resource是资源的抽象和访问接口,简单写了三个实现类
@@ -190,7 +190,7 @@ Resource是资源的抽象和访问接口,简单写了三个实现类
ResourceLoader接口则是资源查找定位策略的抽象,DefaultResourceLoader是其默认实现类
测试:
-```
+```java
public class ResourceAndResourceLoaderTest {
@Test
@@ -222,14 +222,14 @@ public class ResourceAndResourceLoaderTest {
}
```
-## 在xml文件中定义bean
-> 分支:xml-file-define-bean
+## [在xml文件中定义bean](#在xml文件中定义bean)
+> 代码分支:xml-file-define-bean
有了资源加载器,就可以在xml格式配置文件中声明式地定义bean的信息,资源加载器读取xml文件,解析出bean的信息,然后往容器中注册BeanDefinition。
BeanDefinitionReader是读取bean定义信息的抽象接口,XmlBeanDefinitionReader是从xml文件中读取的实现类。BeanDefinitionReader需要有获取资源的能力,且读取bean定义信息后需要往容器中注册BeanDefinition,因此BeanDefinitionReader的抽象实现类AbstractBeanDefinitionReader拥有ResourceLoader和BeanDefinitionRegistry两个属性。
-由于从xml文件中读取的内容是String类型,所以属性仅支持String类型和引用其他Bean。后面会讲到属性编辑器PropertyEditor,实现类型转换。
+由于从xml文件中读取的内容是String类型,所以属性仅支持String类型和引用其他Bean。后面会讲到类型转换器,实现类型转换。
为了方便后面的讲解和功能实现,并且尽量保持和spring中BeanFactory的继承层次一致,对BeanFactory的继承层次稍微做了调整。
@@ -237,7 +237,7 @@ BeanDefinitionReader是读取bean定义信息的抽象接口,XmlBeanDefinition
测试:
bean定义文件spring.xml
-```
+```xml
```
-```
+```java
public class XmlFileDefineBeanTest {
@Test
@@ -280,10 +280,10 @@ public class XmlFileDefineBeanTest {
}
```
-## BeanFactoryPostProcess和BeanPostProcessor
-> 分支:bean-factory-post-processor-and-bean-post-processor
+## [BeanFactoryPostProcessor和BeanPostProcessor](#BeanFactoryPostProcessor和BeanPostProcessor)
+> 代码分支:bean-factory-post-processor-and-bean-post-processor
-BeanFactoryPostProcess和BeanPostProcessor是spring框架中具有重量级地位的两个接口,理解了这两个接口的作用,基本就理解spring的核心原理了。为了降低理解难度分两个小节实现。
+BeanFactoryPostProcessor和BeanPostProcessor是spring框架中具有重量级地位的两个接口,理解了这两个接口的作用,基本就理解spring的核心原理了。为了降低理解难度分两个小节实现。
BeanFactoryPostProcessor是spring提供的容器扩展机制,允许我们在bean实例化之前修改bean的定义信息即BeanDefinition的信息。其重要的实现类有PropertyPlaceholderConfigurer和CustomEditorConfigurer,PropertyPlaceholderConfigurer的作用是用properties文件的配置值替换xml文件中的占位符,CustomEditorConfigurer的作用是实现类型转换。BeanFactoryPostProcessor的实现比较简单,看单元测试BeanFactoryPostProcessorAndBeanPostProcessorTest#testBeanFactoryPostProcessor追下代码。
@@ -291,7 +291,7 @@ BeanPostProcessor也是spring提供的容器扩展机制,不同于BeanFactoryP
BeanPostProcessor的两个方法分别在bean执行初始化方法(后面实现)之前和之后执行,理解其实现重点看单元测试BeanFactoryPostProcessorAndBeanPostProcessorTest#testBeanPostProcessor和AbstractAutowireCapableBeanFactory#initializeBean方法,有些地方做了微调,可不必关注。
-```
+```java
public interface BeanPostProcessor {
/**
* 在bean执行初始化方法之前执行此方法
@@ -308,7 +308,7 @@ public interface BeanPostProcessor {
下一节将引入ApplicationContext,能自动识别BeanFactoryPostProcessor和BeanPostProcessor,就可以在xml文件中配置而不需要手动添加到BeanFactory了。
测试:
-```
+```java
public class BeanFactoryProcessorAndBeanPostProcessorTest {
@Test
@@ -345,14 +345,14 @@ public class BeanFactoryProcessorAndBeanPostProcessorTest {
}
```
-## 应用上下文ApplicationContext
-> 分支:application-context
+## [应用上下文ApplicationContext](#应用上下文ApplicationContext)
+> 代码分支:application-context
应用上下文ApplicationContext是spring中较之于BeanFactory更为先进的IOC容器,ApplicationContext除了拥有BeanFactory的所有功能外,还支持特殊类型bean如上一节中的BeanFactoryPostProcessor和BeanPostProcessor的自动识别、资源加载、容器事件和监听器、国际化支持、单例bean自动初始化等。
BeanFactory是spring的基础设施,面向spring本身;而ApplicationContext面向spring的使用者,应用场合使用ApplicationContext。
-具体实现查看AbstractApplicationContext#refresh方法即可。注意BeanFactoryPostProcessor和BeanPostProcessor的自定识别,这样就可以在xml文件中配置二者而不需要像上一节一样手动添加到容器中了。
+具体实现查看AbstractApplicationContext#refresh方法即可。注意BeanFactoryPostProcessor和BeanPostProcessor的自动识别,这样就可以在xml文件中配置二者而不需要像上一节一样手动添加到容器中了。
从bean的角度看,目前生命周期如下:
@@ -360,8 +360,8 @@ BeanFactory是spring的基础设施,面向spring本身;而ApplicationContext
测试:见ApplicationContextTest
-## bean的初始化和销毁方法
-> 分支:init-and-destroy-method
+## [bean的初始化和销毁方法](#bean的初始化和销毁方法)
+> 代码分支:init-and-destroy-method
在spring中,定义bean的初始化和销毁方法有三种方法:
- 在xml文件中制定init-method和destroy-method
@@ -382,7 +382,7 @@ BeanFactory是spring的基础设施,面向spring本身;而ApplicationContext
测试:
init-and-destroy-method.xml
-```
+```xml
```
-```
+
+```java
public class Person implements InitializingBean, DisposableBean {
private String name;
@@ -433,7 +434,8 @@ public class Person implements InitializingBean, DisposableBean {
//setter and getter
}
```
-```
+
+```java
public class InitAndDestoryMethodTest {
@Test
@@ -444,8 +446,8 @@ public class InitAndDestoryMethodTest {
}
```
-## Aware接口
-> 分支:aware-interface
+## [Aware接口](#Aware接口)
+> 代码分支:aware-interface
Aware是感知、意识的意思,Aware接口是标记性接口,其实现子类能感知容器相关的对象。常用的Aware接口有BeanFactoryAware和ApplicationContextAware,分别能让其实现者感知所属的BeanFactory和ApplicationContext。
@@ -461,7 +463,7 @@ Aware是感知、意识的意思,Aware接口是标记性接口,其实现子
测试:
spring.xml
-```
+```xml
```
-```
+
+```java
public class HelloService implements ApplicationContextAware, BeanFactoryAware {
private ApplicationContext applicationContext;
@@ -501,7 +504,8 @@ public class HelloService implements ApplicationContextAware, BeanFactoryAware {
}
}
```
-```
+
+```java
public class AwareInterfaceTest {
@Test
@@ -514,10 +518,10 @@ public class AwareInterfaceTest {
}
```
-## bean作用域,增加prototype的支持
-> 分支:prototype-bean
+## [bean作用域,增加prototype的支持](#bean作用域增加prototype的支持)
+> 代码分支:prototype-bean
-每次向容器获取prototype作用域bean时,容器都会创建一个新的实例。在BeanDefinition中增加描述bean的作用域的字段scope/singleton/prototype,创建prototype作用域bean时(AbstractAutowireCapableBeanFactory#doCreateBean),不往singletonObjects中增加该bean。prototype作用域bean不执行销毁方法,查看AbstractAutowireCapableBeanFactory#registerDisposableBeanIfNecessary方法。
+每次向容器获取prototype作用域bean时,容器都会创建一个新的实例。在BeanDefinition中增加描述bean的作用域的字段scope,创建prototype作用域bean时(AbstractAutowireCapableBeanFactory#doCreateBean),不往singletonObjects中增加该bean。prototype作用域bean不执行销毁方法,查看AbstractAutowireCapableBeanFactory#registerDisposableBeanIfNecessary方法。
至止,bean的生命周期如下:
@@ -525,7 +529,7 @@ public class AwareInterfaceTest {
测试:
prototype-bean.xml
-```
+```xml
```
-```
+
+```java
public class PrototypeBeanTest {
@Test
@@ -555,8 +560,8 @@ public class PrototypeBeanTest {
}
```
-## FactoryBean
-> 分支:factory-bean
+## [FactoryBean](#FactoryBean)
+> 代码分支:factory-bean
FactoryBean是一种特殊的bean,当向容器获取该bean时,容器不是返回其本身,而是返回其FactoryBean#getObject方法的返回值,可通过编码方式定义复杂的bean。
@@ -564,7 +569,7 @@ FactoryBean是一种特殊的bean,当向容器获取该bean时,容器不是
测试:
factory-bean.xml
-```
+```xml
```
-```
+
+```java
public class CarFactoryBean implements FactoryBean {
private String brand;
@@ -602,7 +608,8 @@ public class CarFactoryBean implements FactoryBean {
}
}
```
-```
+
+```java
public class FactoryBeanTest {
@Test
@@ -616,16 +623,17 @@ public class FactoryBeanTest {
}
```
-## 容器事件和事件监听器
-> 分支:event-and-event-listener
+## [容器事件和事件监听器](#容器事件和事件监听器)
+
+> 代码分支:event-and-event-listener
-ApplicationContext容器提供了完善的时间发布和时间监听功能。
+ApplicationContext容器提供了完善的事件发布和事件监听功能。
ApplicationEventMulticaster接口是注册监听器和发布事件的抽象接口,AbstractApplicationContext包含其实现类实例作为其属性,使得ApplicationContext容器具有注册监听器和发布事件的能力。在AbstractApplicationContext#refresh方法中,会实例化ApplicationEventMulticaster、注册监听器并发布容器刷新事件ContextRefreshedEvent;在AbstractApplicationContext#doClose方法中,发布容器关闭事件ContextClosedEvent。
测试:
event-and-event-listener.xml
-```
+```xml
```
-```
+
+```java
public class EventAndEventListenerTest {
@Test
@@ -654,6 +663,7 @@ public class EventAndEventListenerTest {
}
}
```
+
观察输出:
```
org.springframework.test.common.event.ContextRefreshedEventListener
@@ -661,15 +671,17 @@ org.springframework.test.common.event.CustomEventListener
org.springframework.test.common.event.ContextClosedEventListener
```
-## 切点表达式
-> 分支:pointcut-expression
+# [基础篇:AOP](#基础篇AOP)
+
+## [切点表达式](#切点表达式)
+> 代码分支:pointcut-expression
Joinpoint,织入点,指需要执行代理操作的某个类的某个方法(仅支持方法级别的JoinPoint);Pointcut是JoinPoint的表述方式,能捕获JoinPoint。
最常用的切点表达式是AspectJ的切点表达式。需要匹配类,定义ClassFilter接口;匹配方法,定义MethodMatcher接口。PointCut需要同时匹配类和方法,包含ClassFilter和MethodMatcher,AspectJExpressionPointcut是支持AspectJ切点表达式的PointCut实现,简单实现仅支持execution函数。
测试:
-```
+```java
public class HelloService {
public String sayHello() {
System.out.println("hello");
@@ -677,7 +689,8 @@ public class HelloService {
}
}
```
-```
+
+```java
public class PointcutExpressionTest {
@Test
@@ -692,13 +705,13 @@ public class PointcutExpressionTest {
}
```
-## 基于JDK的动态代理
-> 分支:jdk-dynamic-proxy
+## [基于JDK的动态代理](#基于JDK的动态代理)
+> 代码分支:jdk-dynamic-proxy
AopProxy是获取代理对象的抽象接口,JdkDynamicAopProxy的基于JDK动态代理的具体实现。TargetSource,被代理对象的封装。MethodInterceptor,方法拦截器,是AOP Alliance的"公民",顾名思义,可以拦截方法,可在被代理执行的方法前后增加代理行为。
测试;
-```
+```java
public class DynamicProxyTest {
@Test
@@ -719,13 +732,13 @@ public class DynamicProxyTest {
}
```
-## 基于CGLIB的动态代理
-> 分支:cglib-dynamic-proxy
+## [基于CGLIB的动态代理](#基于CGLIB的动态代理)
+> 代码分支:cglib-dynamic-proxy
基于CGLIB的动态代理实现逻辑也比较简单,查看CglibAopProxy。与基于JDK的动态代理在运行期间为接口生成对象的代理对象不同,基于CGLIB的动态代理能在运行期间动态构建字节码的class文件,为类生成子类,因此被代理类不需要继承自任何接口。
测试:
-```
+```java
public class DynamicProxyTest {
private AdvisedSupport advisedSupport;
@@ -751,13 +764,13 @@ public class DynamicProxyTest {
}
```
-## AOP代理工厂
-> 分支:proxy-factory
+## [AOP代理工厂](#AOP代理工厂)
+> 代码分支:proxy-factory
增加AOP代理工厂ProxyFactory,由AdvisedSupport#proxyTargetClass属性决定使用JDK动态代理还是CGLIB动态代理。
测试:
-```
+```java
public class DynamicProxyTest {
private AdvisedSupport advisedSupport;
@@ -790,8 +803,8 @@ public class DynamicProxyTest {
}
```
-## 几种常用的Advice:BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice...
-> 分支: common-advice
+## [几种常用的Advice:BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice...](#几种常用的AdviceBeforeAdviceAfterAdviceAfterReturningAdviceThrowsAdvice)
+> 代码分支: common-advice
Spring将AOP联盟中的Advice细化出各种类型的Advice,常用的有BeforeAdvice/AfterAdvice/AfterReturningAdvice/ThrowsAdvice,我们可以通过扩展MethodInterceptor来实现。
@@ -802,7 +815,7 @@ Spring将AOP联盟中的Advice细化出各种类型的Advice,常用的有Befor
- [ ] ThrowsAdvice
测试:
-```
+```java
public class WorldServiceBeforeAdvice implements MethodBeforeAdvice {
@Override
@@ -811,7 +824,8 @@ public class WorldServiceBeforeAdvice implements MethodBeforeAdvice {
}
}
```
-```
+
+```java
public class DynamicProxyTest {
private AdvisedSupport advisedSupport;
@@ -840,13 +854,13 @@ public class DynamicProxyTest {
}
```
-## PointcutAdvisor:Pointcut和Advice的组合
-> 分支:pointcut-advisor
+## [PointcutAdvisor:Pointcut和Advice的组合](#PointcutAdvisorPointcut和Advice的组合)
+> 代码分支:pointcut-advisor
Advisor是包含一个Pointcut和一个Advice的组合,Pointcut用于捕获JoinPoint,Advice决定在JoinPoint执行某种操作。实现了一个支持aspectj表达式的AspectJExpressionPointcutAdvisor。
测试:
-```
+```java
public class DynamicProxyTest {
@Test
@@ -876,8 +890,9 @@ public class DynamicProxyTest {
}
```
-## 动态代理融入bean生命周期
-> 分支:auto-proxy
+## [动态代理融入bean生命周期](#动态代理融入bean生命周期)
+
+> 代码分支:auto-proxy
结合前面讲解的bean的生命周期,BeanPostProcessor处理阶段可以修改和替换bean,正好可以在此阶段返回代理对象替换原对象。不过我们引入一种特殊的BeanPostProcessor——InstantiationAwareBeanPostProcessor,如果InstantiationAwareBeanPostProcessor处理阶段返回代理对象,会导致短路,不会继续走原来的创建bean的流程,具体实现查看AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation。
@@ -889,7 +904,7 @@ DefaultAdvisorAutoProxyCreator是处理横切逻辑的织入返回代理对象
测试:
auto-proxy.xml
-```
+```xml
```
-```
+```java
public class AutoProxyTest {
@Test
@@ -931,8 +946,10 @@ public class AutoProxyTest {
}
```
-## PropertyPlaceholderConfigurer
-> 分支:property-placeholder-configurer
+# [扩展篇](#扩展篇)
+
+## [PropertyPlaceholderConfigurer](#PropertyPlaceholderConfigurer)
+> 代码分支:property-placeholder-configurer
经常需要将配置信息配置在properties文件中,然后在XML文件中以占位符的方式引用。
@@ -940,10 +957,11 @@ public class AutoProxyTest {
测试:
car.properties
-```
+```properties
brand=lamborghini
```
-```
+
+```xml
```
-```
+
+```java
public class PropertyPlaceholderConfigurerTest {
@Test
@@ -976,24 +995,934 @@ public class PropertyPlaceholderConfigurerTest {
}
```
+## [包扫描](#包扫描)
+> 代码分支:package-scan
+
+结合bean的生命周期,包扫描只不过是扫描特定注解的类,提取类的相关信息组装成BeanDefinition注册到容器中。
+
+在XmlBeanDefinitionReader中解析``````标签,扫描类组装BeanDefinition然后注册到容器中的操作在ClassPathBeanDefinitionScanner#doScan中实现。
+
+测试:
+```java
+@Component
+public class Car {
+
+}
+```
+
+package-scan.xml
+```xml
+
+
+
+
+
+
+```
+
+```java
+public class PackageScanTest {
+
+ @Test
+ public void testScanPackage() throws Exception {
+ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:package-scan.xml");
+
+ Car car = applicationContext.getBean("car", Car.class);
+ assertThat(car).isNotNull();
+ }
+}
+```
+
+## [@Value注解](#Value注解)
+> 代码分支:value-annotation
+
+注解@Value和@Autowired通过BeanPostProcessor处理。InstantiationAwareBeanPostProcessor增加postProcessPropertyValues方法,在bean实例化之后设置属性之前执行,查看AbstractAutowireCapableBeanFactory#doCreateBean方法。
+
+增加AutowiredAnnotationBeanPostProcessor用于处理注解@Value,@Autowired的处理在下一节实现,在ClassPathBeanDefinitionScanner#doScan将其添加到容器中。查看AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues,其中字符解析器StringValueResolver在PropertyPlaceholderConfigurer中添加到BeanFactory中。
+
+测试:
+```java
+@Component
+public class Car {
+
+ @Value("${brand}")
+ private String brand;
+}
+```
+
+value-annotation.xml
+```xml
+
+
+
+
+
+
+
+
+
+
+```
+
+car.properties
+```properties
+brand=lamborghini
+```
+
+```java
+public class ValueAnnotationTest {
+
+ @Test
+ public void testValueAnnotation() throws Exception {
+ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:value-annotation.xml");
+
+ Car car = applicationContext.getBean("car", Car.class);
+ assertThat(car.getBrand()).isEqualTo("lamborghini");
+ }
+}
+```
+
+## [@Autowired注解](#Autowired注解)
+> 代码分支:autowired-annotation
+
+@Autowired注解的处理见AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
+
+测试:
+```java
+@Component
+public class Car {
+
+}
+
+@Component
+public class Person implements InitializingBean, DisposableBean {
+
+ @Autowired
+ private Car car;
+}
+```
+autowired-annotation.xml
+```xml
+
+
+
+
+
+
+```
+
+```java
+public class AutowiredAnnotationTest {
+
+ @Test
+ public void testAutowiredAnnotation() throws Exception {
+ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:autowired-annotation.xml");
+
+ Person person = applicationContext.getBean(Person.class);
+ assertThat(person.getCar()).isNotNull();
+ }
+}
+```
+## [bug fix:没有为代理bean设置属性(discovered and fixed by @kerwin89)](#bug-fix没有为代理bean设置属性discovered-and-fixed-by-kerwin89)
+> 代码分支: populate-proxy-bean-with-property-values
+
+问题现象:没有为代理bean设置属性
+
+问题原因:织入逻辑在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation中执行,而该方法如果返回非null,会导致"短路",不会执行后面的设置属性逻辑。因此如果该方法中返回代理bean后,不会为代理bean设置属性。
+
+修复方案:跟spring保持一致,将织入逻辑迁移到BeanPostProcessor#postProcessAfterInitialization,即将DefaultAdvisorAutoProxyCreator#postProcessBeforeInstantiation的内容迁移到DefaultAdvisorAutoProxyCreator#postProcessAfterInitialization中。
+
+顺便完善spring的扩展机制,为InstantiationAwareBeanPostProcessor增加postProcessAfterInstantiation方法,该方法在bean实例化之后设置属性之前执行。
+
+至此,bean的生命周期比较完整了,如下:
+
+![](./assets/populate-proxy-bean-with-property-values.png)
+
+测试:
+populate-proxy-bean-with-property-values.xml
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```java
+public class WorldServiceImpl implements WorldService {
+
+ private String name;
+
+ @Override
+ public void explode() {
+ System.out.println("The " + name + " is going to explode");
+ }
+
+ //setter and getter
+}
+```
+
+```java
+public class AutoProxyTest {
+
+ @Test
+ public void testPopulateProxyBeanWithPropertyValues() throws Exception {
+ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:populate-proxy-bean-with-property-values.xml");
+
+ //获取代理对象
+ WorldService worldService = applicationContext.getBean("worldService", WorldService.class);
+ worldService.explode();
+ assertThat(worldService.getName()).isEqualTo("earth");
+ }
+}
+```
+
+## [类型转换(一)](#类型转换一)
+> 代码分支:type-conversion-first-part
+
+spring在org.springframework.core.convert.converter包中定义了三种类型转换器接口:Converter、ConverterFactory、GenericConverter。
+
+### 一、Converter
+```java
+public interface Converter {
+
+ /**
+ * 类型转换
+ */
+ T convert(S source);
+}
+```
+Converter能将S类型的对象转换为T类型的对象,比如将String类型的对象转换为Integer类型的对象的实现类:
+```java
+public class StringToIntegerConverter implements Converter {
+ @Override
+ public Integer convert(String source) {
+ return Integer.valueOf(source);
+ }
+}
+```
+使用:
+```java
+Integer num = new StringToIntegerConverter().convert("8888");
+```
+
+### 二、ConverterFactory
+```java
+public interface ConverterFactory {
+
+ Converter getConverter(Class targetType);
+}
+```
+Converter接口适合一对一的类型转换,如果要将String类型转换为Ineger/Long/Float/Double/Decimal等类型,就要实现一系列的StringToInteger/StringToLongConverter/StringToFloatConverter转换器,非常不优雅。
+
+ConverterFactory接口则适合一对多的类型转换,可以将一种类型转换为另一种类型及其子类。比如将String类型转换为Ineger/Long/Float/Double/Decimal等Number类型时,只需定义一个ConverterFactory转换器:
+```java
+public class StringToNumberConverterFactory implements ConverterFactory {
+
+ @Override
+ public Converter getConverter(Class targetType) {
+ return new StringToNumber(targetType);
+ }
+
+ private static final class StringToNumber implements Converter {
+
+ private final Class targetType;
+
+ public StringToNumber(Class targetType) {
+ this.targetType = targetType;
+ }
+
+ @Override
+ public T convert(String source) {
+ if (source.length() == 0) {
+ return null;
+ }
+
+ if (targetType.equals(Integer.class)) {
+ return (T) Integer.valueOf(source);
+ } else if (targetType.equals(Long.class)) {
+ return (T) Long.valueOf(source);
+ }
+ //TODO 其他数字类型
+
+ else {
+ throw new IllegalArgumentException(
+ "Cannot convert String [" + source + "] to target class [" + targetType.getName() + "]");
+ }
+ }
+ }
+
+}
+```
+使用:
+```java
+StringToNumberConverterFactory converterFactory = new StringToNumberConverterFactory();
+Converter stringToIntegerConverter = converterFactory.getConverter(Integer.class);
+Integer num = stringToIntegerConverter.convert("8888");
+```
+### 三、GenericConverter
+```java
+public interface GenericConverter {
+ Set getConvertibleTypes();
+ Object convert(Object source, Class sourceType, Class targetType);
+}
+```
+String类型转换为Boolean类型的实现类:
+```java
+public class StringToBooleanConverter implements GenericConverter {
+ @Override
+ public Set getConvertibleTypes() {
+ return Collections.singleton(new ConvertiblePair(String.class, Boolean.class));
+ }
+ @Override
+ public Object convert(Object source, Class sourceType, Class targetType) {
+ return Boolean.valueOf((String) source);
+ }
+}
+```
+使用:
+```java
+Boolean flag = new StringToBooleanConverter().convert("true", String.class, Boolean.class);
+```
+ConversionService是类型转换体系的核心接口,将以上三种类型转换器整合到一起,GenericConversionService是其实现类,DefaultConversionService在GenericConversionService的基础上添加内置转换器。
+测试见TypeConversionFirstPartTest。
+## [类型转换(二)](#类型转换二)
+> 代码分支:type-conversion-second-part
+上一节实现了spring中的类型转换体系,本节将类型转换的能力整合到容器中。
+为了方便使用,提供了创建ConversionService的FactoryBean——ConversionServiceFactoryBean。
+如果有定义ConversionService,在AbstractApplicationContext#finishBeanFactoryInitialization方法中设置到容器中。
+类型转换的时机有两个:
+- 为bean填充属性时,见AbstractAutowireCapableBeanFactory#applyPropertyValues
+- 处理@Value注解时,见AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
+你可能会有疑问,如果没有定义ConversionService,是怎么进行基本类型的转换的?其实spring为了向下兼容保留了一套比较旧的类型转换机制,没有定义ConversionService时会使用其进行基本类型的转换工作,不必关注旧的类型转换机制。
+测试:
+```java
+public class Car {
+ private int price;
+ private LocalDate produceDate;
+}
+```
+```java
+public class StringToLocalDateConverter implements Converter {
+ private final DateTimeFormatter DATE_TIME_FORMATTER;
+ public StringToLocalDateConverter(String pattern) {
+ DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(pattern);
+ }
+ @Override
+ public LocalDate convert(String source) {
+ return LocalDate.parse(source, DATE_TIME_FORMATTER);
+ }
+}
+```
+
+type-conversion-second-part.xml
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```java
+public class TypeConversionSecondPartTest {
+
+ @Test
+ public void testConversionService() throws Exception {
+ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:type-conversion-second-part.xml");
+
+ Car car = applicationContext.getBean("car", Car.class);
+ assertThat(car.getPrice()).isEqualTo(1000000);
+ assertThat(car.getProduceDate()).isEqualTo(LocalDate.of(2021, 1, 1));
+ }
+}
+```
+
+# [高级篇](#高级篇)
+
+## [解决循环依赖问题(一):没有代理对象](#解决循环依赖问题一没有代理对象)
+> 代码分支:circular-reference-without-proxy-bean
+
+虽然放在高级篇,其实解决循环依赖问题的方法非常简单。
+
+先理解spring中为什么会有循环依赖的问题。比如如下的代码
+
+```java
+public class A {
+
+ private B b;
+
+ //getter and setter
+}
+```
+
+```java
+public class B {
+
+ private A a;
+
+ //getter and setter
+}
+```
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+A依赖B,B又依赖A,循环依赖。容器加载时会执行依赖流程:
+
+- 实例化A,发现依赖B,然后实例化B
+- 实例化B,发现依赖A,然后实例化A
+- 实例化A,发现依赖B,然后实例化B
+- ...
+
+死循环直至栈溢出。
+
+解决该问题的关键在于何时将实例化后的bean放进容器中,设置属性前还是设置属性后。现有的执行流程,bean实例化后并且设置属性后会被放进singletonObjects单例缓存中。如果我们调整一下顺序,当bean实例化后就放进singletonObjects单例缓存中,提前暴露引用,然后再设置属性,就能解决上面的循环依赖问题,执行流程变为:
+
+- 步骤一:getBean(a),检查singletonObjects是否包含a,singletonObjects不包含a,实例化A放进singletonObjects,设置属性b,发现依赖B,尝试getBean(b)
+- 步骤二:getBean(b),检查singletonObjects是否包含b,singletonObjects不包含b,实例化B放进singletonObjects,设置属性a,发现依赖A,尝试getBean(a)
+- 步骤三:getBean(a),检查singletonObjects是否包含a,singletonObjects包含a,返回a
+- 步骤四:步骤二中的b拿到a,设置属性a,然后返回b
+- 步骤五:步骤一中的a拿到b,设置属性b,然后返回a
+
+可见调整bean放进singletonObjects(人称一级缓存)的时机到bean实例化后即可解决循环依赖问题。但为了和spring保持一致,我们增加一个二级缓存earlySingletonObjects,在bean实例化后将bean放进earlySingletonObjects中(见AbstractAutowireCapableBeanFactory#doCreateBean方法第6行),getBean()时检查一级缓存singletonObjects和二级缓存earlySingletonObjects中是否包含该bean,包含则直接返回(见AbstractBeanFactory#getBean第1行)。
+
+单测见CircularReferenceWithoutProxyBeanTest#testCircularReference。
+
+增加二级缓存,不能解决有代理对象时的循环依赖。原因是放进二级缓存earlySingletonObjects中的bean是实例化后的bean,而放进一级缓存singletonObjects中的bean是代理对象(代理对象在BeanPostProcessor#postProcessAfterInitialization中返回),两个缓存中的bean不一致。比如上面的例子,如果A被代理,那么B拿到的a是实例化后的A,而a是被代理后的对象,即b.getA() != a,见单测CircularReferenceWithProxyBeanTest。
+
+下一节填坑。
+
+## [解决循环依赖问题(二):有代理对象](#解决循环依赖问题二有代理对象)
+> 代码分支:circular-reference-with-proxy-bean
+
+解决有代理对象时的循环依赖问题,需要提前暴露代理对象的引用,而不是暴露实例化后的bean的引用(这是上节的遗留问题的原因,应该提前暴露A的代理对象的引用)。
+
+spring中用singletonFactories(一般称第三级缓存)解决有代理对象时的循环依赖问题。在实例化后提前暴露代理对象的引用(见AbstractAutowireCapableBeanFactory#doCreateBean方法第6行)。
+
+getBean()时依次检查一级缓存singletonObjects、二级缓存earlySingletonObjects和三级缓存singletonFactories中是否包含该bean。如果三级缓存中包含该bean,则挪至二级缓存中,然后直接返回该bean。见AbstractBeanFactory#getBean方法第1行。
+
+最后将代理bean放进一级缓存singletonObjects,见AbstractAutowireCapableBeanFactory第104行。
+
+单测见CircularReferenceWithProxyBeanTest。
+
+## [支持懒加载和多切面增强(By @zqczgl)](#支持懒加载和多切面增强by-zqczgl)
+
+### [懒加载](#懒加载)
+
+> 代码分支: lazy-init-and-multi-advice
+
+事实上,并不是所有的bean在初始化容器的时候都会创建。随着项目规模的不断扩大,bean的数目也越来越多。如果每次启动容器都需要加载大量的bean,这无疑会带来大量的资源浪费。所有spring提供了懒加载机制,我们可以将我们认为暂时用不到的bean设为懒加载,这样只有在我们需要这个bean的时候这个bean才会被创建。
+
+测试
+
+lazy-test.xml
+
+```java
+//只有当bean是单例且不为懒加载才会被创建
+public void preInstantiateSingletons() throws BeansException {
+ beanDefinitionMap.forEach((beanName, beanDefinition) -> {
+ if(beanDefinition.isSingleton()&&!beanDefinition.isLazyInit()){
+ getBean(beanName);
+ }
+ });
+ }
+```
+
+```java
+public class LazyInitTest {
+ @Test
+ public void testLazyInit() throws InterruptedException {
+ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:lazy-test.xml");
+ System.out.println(System.currentTimeMillis()+":applicationContext-over");
+ TimeUnit.SECONDS.sleep(1);
+ Car c= (Car) applicationContext.getBean("car");
+ c.showTime();//显示bean的创建时间
+ }
+}
+```
+
+```xml
+
+
+
+
+
+
+
+```
+
+关闭懒加载的输出:
+
+```
+1671698959957:applicationContext-over
+1671698959951:bean create
+```
+
+开启懒加载:
+
+```
+1671699030293:applicationContext-over
+1671699031328:bean create
+```
+
+可以清楚的看到开启和不开启懒加载bean的创建时机的差异
+
+### [多个切面匹配同一方法](#多个切面匹配同一方法)
+
+> 代码分支: lazy-init-and-multi-advice
+
+虽然在前面我们完成了对方法的增强,但并不完美。我们的目前的代码只能支持对方法的单个增强。作为spring的核心功能如果不支持多切面的话有点太别扭了。spring利用了拦截器链来完成了对多个切面的支持。
+
+#### [ProxyFactory](#ProxyFactory)
+
+让我们从ProxyFactory开始,来看一下代理对象的整个创建流程。至于为什么从ProxyFactory开,这是因为代理对象最终是用ProxyFactory的getProxy()函数来获得的。
+
+```java
+public class ProxyFactory extends AdvisedSupport{
+
+
+ public ProxyFactory() {
+ }
+
+ public Object getProxy() {
+ return createAopProxy().getProxy();
+ }
+
+ private AopProxy createAopProxy() {
+ if (this.isProxyTargetClass()||this.getTargetSource().getTargetClass().length==0) {
+ return new CglibAopProxy(this);
+ }
+ return new JdkDynamicAopProxy(this);
+ }
+}
+```
+
+为了更贴合spring的实现,这里更改了ProxyFactory使其继承了AdvisedSupport,正如spring源码中做的那样。
+
+#### [基于JDK动态代理](#基于JDK动态代理)
+
+ProxyFactory只是简单的做了下选择,当我们设置proxyTargetClass属性或者被代理对象没有接口时会调用cjlib动态代理,否则调用jdk动态代理。二者实现并没有太大区别,这里只贴出jdk动态代理的实现。
+
+```java
+ public Object getProxy() {
+ return Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getTargetClass(), this);
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ // 获取目标对象
+ Object target=advised.getTargetSource().getTarget();
+ Class> targetClass = target.getClass();
+ Object retVal = null;
+ // 获取拦截器链
+ List
\ No newline at end of file
+
diff --git a/src/test/resources/autowired-annotation.xml b/src/test/resources/autowired-annotation.xml
new file mode 100644
index 0000000..3f9f12d
--- /dev/null
+++ b/src/test/resources/autowired-annotation.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/circular-reference-with-proxy-bean.xml b/src/test/resources/circular-reference-with-proxy-bean.xml
new file mode 100644
index 0000000..c479df9
--- /dev/null
+++ b/src/test/resources/circular-reference-with-proxy-bean.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/circular-reference-without-proxy-bean.xml b/src/test/resources/circular-reference-without-proxy-bean.xml
new file mode 100644
index 0000000..9babe20
--- /dev/null
+++ b/src/test/resources/circular-reference-without-proxy-bean.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/lazy-test.xml b/src/test/resources/lazy-test.xml
new file mode 100644
index 0000000..57ca4f8
--- /dev/null
+++ b/src/test/resources/lazy-test.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/src/test/resources/package-scan.xml b/src/test/resources/package-scan.xml
new file mode 100644
index 0000000..98cf664
--- /dev/null
+++ b/src/test/resources/package-scan.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/populate-proxy-bean-with-property-values.xml b/src/test/resources/populate-proxy-bean-with-property-values.xml
new file mode 100644
index 0000000..20c0f01
--- /dev/null
+++ b/src/test/resources/populate-proxy-bean-with-property-values.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/type-conversion-second-part.xml b/src/test/resources/type-conversion-second-part.xml
new file mode 100644
index 0000000..2764aac
--- /dev/null
+++ b/src/test/resources/type-conversion-second-part.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/value-annotation.xml b/src/test/resources/value-annotation.xml
new file mode 100644
index 0000000..3f9f12d
--- /dev/null
+++ b/src/test/resources/value-annotation.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file