整体步骤包含两部分内容:默认为spring框架内容,使用[应用]标注的表示:这一步骤是属于APP应用内部的
- 创建管理容器
SpringApplicationContext
:容器用于加载配置文件,并提供获取Bean的方法getBean() - (应用)创建一个应用配置类
AppConfig
: 用于标识spring框架需要扫描的包路径 - (应用)创建两个类 UserService,XxUtils:用于一会儿交给spring框架来扫描,一个是Bean对象,一个普通的类
- 创建注解
ComponentScan
,Component
: 通过注解的方式来标记:哪些包需要被扫描,被扫描包目录下使用了@Component
标记的类才就是Bean对象 - 通过
类加载器
来获取注解标记的所有类对象
,并准备将类对象转换为Bean对象的指定数据类型BeanDefinition
- 此时,我们将 Bean 设计为两种类型:
单例 singleton
,原型 prototype
. 因此创建一个注解@Scope
用来标记这个对象是哪一种Bean类型 - 在扫描过程中,将所有的Bean都以 <beanName,beanDefinition>的键值对存入
beanDefinitionMap
中管理。 - 扫描完成后,为所有bean对象创建对应实例。这里:scope作用域为单例的Bean首先在
beanDefinitionMap
中查找是否已创建,没有则创建,有则返回已创建的,scope作用域为原型的Bean直接创建对应实例
- 依赖注入实现。所有的Bean已被扫描并存储在
beanDefinitionMap
中,并为所有的单例Bean创建了实例,所有的原型Bean仅仅是存储了其Bean数据结构beanDefinition
- 容器感知beanNameAware: 对于某一个Bean本身(userService)而言,使用者是不知道关于容器的信息。实现 beanNameAware容器感知
- Bean初始化方式: 在spring源码中提供了两种Bean初始化方式,这里实现其中之一
initializingBean
- AOP实现:通过JAVA-JDK 动态代理实现,即实现AOP切面,实现位置位于
BeanPostProcessor
.需要注意 代理是对 某一个具体对象的某种行为进行代理,所以必须被代理的对象必须至少实现一个接口
在书写源码的过程中,遇到不清晰的知识点,记录在文件夹 source-ex
中
- 步骤6 中的scope
. 对于scope的单例和原型类型,我们可以简单采用enum枚举类型,也可以尝试像spring源码中定义
org.springframework.beans.factory.config.Scope
接口 - 步骤8 创建Bean实例 java clazz.getDeclaredConstructor().newInstance() 和 class.newInstance() 的区别
- 步骤10 InitializingBean作用
- 步骤12 jdk-动态代理
- 其他源码实现