Spring是如何启动的
Spring最大的核心就是Bean容器;
容器: 从对象创建,使用和销毁全部由容器帮我们控制,用户仅仅使用就可以。
两大核心
- IOC 控制反转
- AOP 面向切面编程
思考:我们是如何使用Spring的呢?
加入从配置文件中加载bean 我们猜想一下大致流程是怎样的
1 | <bean id=getPerson class=com.ibli.Person> |
配置文件如上👆,这里是伪代码!
先猜想大致流程:
通过上面猜想创建的对象流程,创建出对象,对象已经好了,就是使用了,那么如何使用呢?
一般情况下我们会可以这样使用,写一下伪代码吧👇:
1 | 创建一个ApplicationContext对象 |
思考,创建的对象如何存储? 或者容器到底是什么呢? 应该可以猜到是Map结构,具体是什么Map,先不管;
1、首先容器是创建好的,容器创建好之后,才可以加载配置文件
也就是我们猜想的Map
2、加载配置文件
配置文件可能会有多种方式,比如XML格式,property格式,yaml格式,注解格式,这个格式各不相同,又是如何加载的呢?
Spring提供了一个接口,BeanDefinitionReader,它有一个抽象实现类AbstractBeanDefinitionReader,不同配置文件的Reader来继承这个抽象类,实现它们自己的逻辑;
1 | public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader |
3、读取的配置文件会转换成Spring定义的格式,也就是BeanDefinition;
BeanDefinition定义了类的所有相关的数据; 此时得到的BeanDefinition的属性值只是「符号类型」,并不是真正的属性值;
我们可能会见过这中加载数据源的方式👇
1 | <bean id=dataSource class=com.alibab.durid.pool.DruidDataSource> |
数据源的具体配置是放在配置文件中的,当通过XmlBeanDefinitionReader读取并解析到的BeanDefinition,仅仅是将Xml中的文件数据存放到BeanDefinition中,属性的值是${jdbc.url}而不是真正的我们数据源的地址;
4、得到所有的BeanDefinition之后,通过BeanFactoryPostProcessor来处理上一步骤中,属性value不是真实数据的问题
比如PlaceHolderConfigurerSupport(占位符处理) 经过工厂后置处理器处理之后,BeanDefinition的属性值就是真实需要的数据了;
5、BeanDefinition数据准备完成之后,由BeanFactory来完成Bean的创建
- 实例化 对象中分配堆内存等操作
反射调用无参构造函数 创建对象 但是属性是空的
- 初始化
6、初始化之前需要准备的工作
1、准备BeanPostProcessors
2、观察者模式,准备监听器 事件 广播器
7、初始化环节有很多步骤
对象的填充
其实就是调用get/set方法对属性赋值
调用aware方法
如果我们的对象中的属性是BeanFactory 我们不用自己去完成setBeanFactory方法,只需要当前类实现BeanFactoryAware方法即可
1
2
3public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory var1) throws BeansException;
}处理before操作
调用init方法
执行after方法
before和after此处是调用的BeanPostProcessor的方法
1
2
3
4// 前置方法
postProcessBeforeInitialization
// 后置方法
postProcessAfterInitialization
8、执行到此,完成对象的创建,得到一个可以使用的对象