综述
这个系列主要是从一个普通开发者的角度出发,思考Spring整个框架的设计思想和整个流程的源码分析,以及常见组件的分析。
这个系列不涉及过于底层的源码,也不涉及一些过于详细的概念解释,我们还是从整体到局部,主要把流程讲清楚,一些细节上的地方就留给读者深入分析。
目录
1. 搭建Demo项目
2. Spring 相关概念解释
3. Spring启动流程图
4. Spring启动流程分析
内容
搭建Demo项目
我们可以创建一个demo工程来看最简单的一个Spring工程启动流程,可以参考以下流程创建和配置:
- 创建Maven工程(这个步骤省略)
- 引入Spring依赖(Spring 版本:5.3.23)
...
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.version>5.3.23</org.springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
</dependencies>
...
注意: 这里为了依赖最小化,不引入过多的Spring jar包,只引入最小的依赖,这里也可以看出来Spring是一个高度模块化的框架,开发者可以按照自己的需要引入对应的模块
3. 引入基本的Spring配置文件(放在resources目录下面)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.example"/>
</beans>
注意:这里为了自动扫描Bean,我们就引入了自动包扫描机制
4. Java启动代码
...
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
System.out.println(Arrays.toString(applicationContext.getBeanDefinitionNames()));
}
....
- 启动代码,查看输出
至此,我们已经将整个demo项目正常启动起来了
Spring 相关概念解释
| 名称 | 说明 |
|---|---|
| BeanFactory | 用于管理Bean的类,可认为是整个Spring框架的基石,所有的Bean加载和生命周期管理都通过该类实现 |
| ApplicationContext | 该类的作用与BeanFactory的作用一样,只不过ApplicationContext在他的基础上集成了更方便的能力,例如:国际化、事件监听、xml配置文件加载等 |
| BeanDefinition | Bean定义信息,Spring使用这个类作为作为承载Bean定义信息的结构,例如:scope信息,beanName等 |
| BeanFactoryPostProcessor | 这个接口是用来定义BeanFactory加载玩BeanDefinition信息后需要进行特殊处理行为的后处理器,通过这个扩展点可以实现在BeanDefinition加载后bean加载前进行特殊处理,例如注入${...}参数 |
| BeanPostProcessor | 这个接口是用于定义Bean初始化前后需要进行特殊处理行为的后处理器,通过这个拓展点可以实现Bean初始化前后进行特殊处理,例如Aop增强 |
注意:
- BeanFactoryProcessor和BeanFactoryProcessor这两个后处理器面对的处理对象和处理时机不一样
- BeanFactoryProcessor是在BeanFactory加载完BeanDefinition信息后进行再次加工处理,这里还没有Bean产生,只是产生了BeanDefinition而已
- 而BeanPostProcessor是在每个Bean实例化过程对Bean进行改造处理的,例如在初始化前对某个参数进行调整,或者在初始化后对bean进行统计等,这两个概念需要区别开来,不要混为一体
Spring启动流程图
首先列入我理解的Spring启动流程分析图,这里关注Spring的主要流程,例如一些Aware接口的设置,一些属性解析还有Aop增强都是在Spring启动流程中的拓展点进行处理,实际上是属于Spring增强能力的一部分,后续在分析过程中进行深入,而在流程图这里就不列举,避免影响我们对整个启动流程的分析
Spring启动流程分析
在整个Spring框架中最重要的就是IOC容器,通过这个容器可以对所有需要的bean进行一个生命周期的管理,例如创建、使用、销毁等的操作。通过这个思想,我们可以得知Spring框架需要实现通过读取bean的定义,然后将bean加载到容器中,而如何去读取bean呢?这个时候就体现了Spring的设计思想了。
首先,bean配置信息的来源可以多种多样,例如:通过xml配置文件,通过注解的方式实现bean信息的配置,所以这里Spring就提供了多种不同的Reader类,用于读取对应的配置信息,然后将配置信息抽象成BeanDefinition类,这个类用来定义bean的信息,例如:bean名称,bean的scope等等,注意这里只是加载了bean的定义信息,而不是真正的bean实例。
在完成了读取bean信息之后,实际上已经构建出一个可用的beanFactory信息,后面就可以根据具体的信息进行初始化了,而在这个时候Spring就提供了一个拓展点,用于对BeanDefinition存储的信息进行修改,像上面流程图写的,在完成加载beanDefinition后通过BeanFactoryPostProcessor进行拓展(常见的property文件属性注入就是这个阶段)。
而在完成以上几步之后,Spring就开始进行bean的实例化工作了,而在Spring框架的流程中bean的生成实际上是分成两个大步骤实现的:
bean生成 = bean实例化(反射实现)+ bean初始化(属性赋值 + 自定义初始化方法)
而这个时候,Spring框架给我们留出来第二个拓展点BeanPostProcessor,主要用于在Bean初始化的前后进行bean信息的修改,通过这个拓展点我们可以实现在获取bean的时候进行能力增强,例如:AOP等。
而以上就是我对整个bean启动流程的简单理解,后续系列会结合源码对每个环节进行解析,深入理解Spring的启动流程。