Spring bean的简单加载流程说明

Spring的bean 初始化流程大致可以分为以下两个过程,这里我们以ApplicationContext为例子来说明

1.容器自身的启动阶段

容器启动伊始,首先会通过某种途径加载Configuration MetaData。除了代码方式比较直接,在大
部分情况下,容器需要依赖某些工具类(BeanDefinitionReader)对加载的Configuration MetaData进行解析和分析,并将分析后的信息编组为相应的BeanDefinition,最后把这些保存了bean定义必要信息的BeanDefinition,注册到相应的BeanDefinitionRegistry,这样容器启动工作就完成了

借鉴《Spring揭秘》书上的图
PB58jP.md.png

第一阶段中
- 对加载的Configuration MetaData进行解析和分析,并将分析后的信息编组为相应的BeanDefinition这一阶段一般不需要我们自己太关注
- 但是BeanFactoryPostProcessor 这个机制我们会用到,Spring提供的几个实现类如下
- 比如PropertyPlaceholderConfigurer,我们常用来处理数据库资源文件中的占位符,允许我们在XML配置文件中使用占位符(PlaceHolder),并将这些占位符所代表的资源单独配置到简单的properties文件中来加载
- CustomEditorConfigurer来 将xml中定义的属性值(文本)转换为实际bean中的属性
- PropertyOverrideConfigurer 指定一个properties文件,可以对容器中所有的bean属性进行替换,格式如下:

        beanName.propertyName=value

2.bean的初始化阶段

经过第一阶段,现在所有的bean定义信息都通过BeanDefinition的方式注册到了BeanDefini-
tionRegistry中。当某个请求方通过容器的getBean方法明确地请求某个对象,或者因依赖关系容器需要隐式地调用getBean方法时,就会触发第二阶段的活动。
该阶段,容器会首先检查所请求的对象之前是否已经初始化。如果没有,则会根据注册的
BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。如果该对象实现了某些回调接口,也会根据回调接口的要求来装配它。当该对象装配完毕之后,容器会立即将其返回请求方使用。

第二个阶段中:

容器在内部实现的时候,采用“策略模式(Strategy Pattern)”来决定采用何种方式初始化bean实例。
通常,可以通过反射或者CGLIB动态字节码生成来初始化相应的bean实例或者动态生成其子类。spring容器默认的接口策略的实现类为CglibSubclassingInstantiationStrategy,即可以动态生成某个类的子类

graph TB
A[BeanDefinition读取]-->C[生成BeanWrapper类]
B[接口策略决定实例化方式]-->C[生成BeanWrapper类]
C[生成BeanWrapper类]-->D[PropertyEditorRegistry和TypeConverter接口]
D[PropertyEditorRegistry和TypeConverter接口]-->|利用CustomEditorConfigurer设置属性|E[生成Bean]

第二阶段的初始化流程

PB7IiD.png

下面对图中标记部分做一些补充

  • 1号箭头指的InstantiationAwareBeanPostProcessor,据《spring揭秘》书上所说是一种短路 的 BeanPostProcessor,在所有的步骤之前,也就是实例化bean对象步骤之前,容器会首先检查容器中是否注册有InstantiationAwareBeanPost Processor类型的BeanPostProcessor。如果有,首先使用相应的InstantiationAwareBean- PostProcessor来构造对象实例。构造成功后直接返回构造完成的对象实例,而不会按照“正规的流程”继续执行。这就是它可能造成“短路”的原因。(开发者基本不会使用这个)
  • 2号箭头指的是BeanNameAware 和 BeanFactoryAware(以及图上没有的BeanClassLoaderAware) 都是由Spring的去检测业务bean是否实现相应的接口,来给业务bean注入相应的属性

  • 3号箭头指的是BeanPostProcessor接口, 在ApplicationContext中 的ApplicationContextAwareProcessor实现了该接口,他会扫描容器中业务bean,是否实现ResourceLoaderAware 、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware 接口,然后也会给业务bean设置相关属性(与第二点不同的地方在于检测的时机不同,第二点由Spring容器检测,第三点由处理器检测,差别不是很大)


参考《spring揭秘》 和 《精通Spring4.x++企业应用开发实战》

猜你喜欢

转载自blog.csdn.net/whp404/article/details/81412417