Spring是spring生态圈的基石,大家工作中常用的SSM框架,SpringBoot框架都是在Spring基础上衍生的,所以想更好的了解它们深入学习Spring是必不可少的。本章以综述的方式带大家快速了解Spring核心流程。

XML配置文件

使用函数

由上述Spring的使用过程可以衍生出两个问题:
1. XML配置文件加载解析到容器中并实例化成Bean对象的主要步骤是什么?
2. IOC容器是以什么数据结构存储Bean对象的?
接下来我们就来探讨以上这两个问题。

相信大家通过观察上图很容易就发现出问题,难道Bean的定义信息只能通过XML配置文件来定义吗?显然不是。Spring为了提高拓展性提供了一个Bean定义信息的接口,只要想承载Bean定义信息的只需要实现这个规范即可。
如图所示:

BeanDefinition对象就是BeanDefinitionReader在解析Bean定义信息时,将Bean的定义信息封装成的对象。例如将xml文件中的bean标签的内容封装成对象,从这个对象中我们可以获取所有bean标签中定义的信息,也可以修改配置文件中定义的信息。
看源码BeanDefinition的方法:

这个接口是所有想要承载Bean定义信息所需要实现的接口,该接口定义了一系列的规范。
看BeanDefinitionReader的子实现类

相信很多小伙伴们觉得有了BeanDefinition对象就可以直接实例化Bean对象,这种思想咋一看好像是对的,毕竟都有了Bean的定义信息直接按照Bean定义信息封装的对象BeanDefinition来实例化对象不就可以了吗?但是如果在程序运行过程中要动态改变Bean的信息怎么办?要随时改变Bean的信息怎么办?例如<property name=url value=${jdbc.url},在这个情况下是绝对不能直接将BeanDefinition实例化成Bean对象的,因为IOC容器并不认识 ${jdbc.url},所以我们要在对象真正实例化进入容器之前进行拦截,替换掉 ${jdbc.url}。
我们可以在Bean对象真正被实例化出来之前,加BeanFactoryPostProcessor,来达到动态修改Bean对象信息的目的。

输出结果图:

现在我们解决2.5提出的问题 ${jdbc_url}是怎么样被替换的呢?
源码截图:


对象实例化的方式一般有两种,一种是直接new,一种是通过反射,那么spring在实例化bean对象的时候采用那种方式呢?
spring是通过反射来实例化bean对象的
1. new对象的方式只能通过默认构造方法或者用户自定义的构造方法来为对象属性初始化,而通过反射的方式
可以操作一个对象的所有属性,所有方法,所有注解,功能显得更加强大灵活,因此spring是通过反射来实
化bean对象的。

填充属性阶段会执行配置文件中property标签的内容,通过setter方法给对象的属性赋值。
注意:填充属性阶段是通过setter方法给属性赋值的,对象对应的属性必须有setter方法,否则property标签会失效。
可以在类的成员方法中写一个初始化方法,在xml配置文件中的bean标签中指定该方法为init-method,那么在对象初始化的执行初始化方法阶段就会执行该方法。
示例
实体类

测试类

结果:


Aware接口是一个标记接口,顾名思义这个接口是感知的意思,即bean对象能够感知到所在的spring 容器对象。只要一个对象实现了Aware接口,并重写了setter方法,当这个对象交由spring容器创建的时候,spring容器会将自身的对象作为参数传入,这样我们就可以通过该bean对象的实例获取容器对象。
示例
实体类

测试类

结果

spring容器的Aware接口有很多,大家可以通过源码查看。
spring容器是以Map集合来存储bean对象的。
那么Map集合的key和value的类型有多少种呢?
key为bean对象的id值,value为bean对象
相当于是以by-Name方式从容器中取出对象
key为bean对象的类信息,value为bean对象
相当于是以by-Type方式从容器中取出对象
key为bean对象的id值,value为生产bean对象的工厂
key为bean对象的id值,value为bean对象的定义信息。
