Spring框架分析(1)---启动流程简单分析

113 阅读4分钟

综述

这个系列主要是从一个普通开发者的角度出发,思考Spring整个框架的设计思想和整个流程的源码分析,以及常见组件的分析。

这个系列不涉及过于底层的源码,也不涉及一些过于详细的概念解释,我们还是从整体到局部,主要把流程讲清楚,一些细节上的地方就留给读者深入分析。

目录

1. 搭建Demo项目
2. Spring 相关概念解释
3. Spring启动流程图 4. Spring启动流程分析

内容

搭建Demo项目

我们可以创建一个demo工程来看最简单的一个Spring工程启动流程,可以参考以下流程创建和配置:

  1. 创建Maven工程(这个步骤省略)
  2. 引入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()));
}
....
  1. 启动代码,查看输出

image.png

至此,我们已经将整个demo项目正常启动起来了

Spring 相关概念解释

名称说明
BeanFactory用于管理Bean的类,可认为是整个Spring框架的基石,所有的Bean加载和生命周期管理都通过该类实现
ApplicationContext该类的作用与BeanFactory的作用一样,只不过ApplicationContext在他的基础上集成了更方便的能力,例如:国际化、事件监听、xml配置文件加载等
BeanDefinitionBean定义信息,Spring使用这个类作为作为承载Bean定义信息的结构,例如:scope信息,beanName等
BeanFactoryPostProcessor这个接口是用来定义BeanFactory加载玩BeanDefinition信息后需要进行特殊处理行为的后处理器,通过这个扩展点可以实现在BeanDefinition加载后bean加载前进行特殊处理,例如注入${...}参数
BeanPostProcessor这个接口是用于定义Bean初始化前后需要进行特殊处理行为的后处理器,通过这个拓展点可以实现Bean初始化前后进行特殊处理,例如Aop增强

注意

  1. BeanFactoryProcessor和BeanFactoryProcessor这两个后处理器面对的处理对象和处理时机不一样
  2. BeanFactoryProcessor是在BeanFactory加载完BeanDefinition信息后进行再次加工处理,这里还没有Bean产生,只是产生了BeanDefinition而已
  3. 而BeanPostProcessor是在每个Bean实例化过程对Bean进行改造处理的,例如在初始化前对某个参数进行调整,或者在初始化后对bean进行统计等,这两个概念需要区别开来,不要混为一体

Spring启动流程图

Spring启动流程.png 首先列入我理解的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的启动流程。