Spring源码--IOC的初始化过程--01
一、前言
- 最近开始重温Spring,觉得只知道会用是不行的,所以想尝试着结合资料观摩一下源码
- 由于Spring源码非常的多,一步步都看完明显是不现实的,所以只记录自己觉得重要的步骤,其它细枝末节不去纠结
- 本人才疏学浅,以下的总结完全主观,在逐渐学习的过程中也会不断更新表述不合适的地方,如果有错误希望能包涵并指出!
二、源码阅读
- debug定位到容器创建位置,进入源码
- 调用了3个参数的构造方法创建ClassPathXmlApplicationContext对象,将传入的字符串转换成一个数组
- 进入到该构造方法内部,第一步为调用super(parent)初始化父类对象
-
super(parent)
- 一路调用父类的构造方法,最后进入AbstractApplicationContext类的构造方法初始化该类
- 由于AbstractApplicationContext继承了DefaultResourceLoader,所以需要先初始化DefaultResourceLoader,进入到DefaultResourceLoader类中去指定默认的类加载器(上下文类加载器)
- 回到AbstractApplicationContext类中,初始化了一些容器后开始执行构造方法中的语句,从名字我们可以推测这里指定的是资源解析器
- 进入后发现里面创建的是PathMatchingResourcePatternResolver,从上面的注释我们可以知道这个解析器是用来定位需要解析资源的位置的
- 当创建完PathMatchingResourcePatternResolver后super(parent)语句便结束了,总结
- 对ClassPathXmlApplicationContext的父类AbstractApplicationContext进行初始化
- 初始化DefaultResourceLoader类,并将其中的classLoader属性指定为AppClassLoader
- 创建PathMatchingResourcePatternResolver实例并返回给AbstractApplicationContext中的resourcePatternResolver属性
- 一路调用父类的构造方法,最后进入AbstractApplicationContext类的构造方法初始化该类
-
setConfigLocations(configLocations);
- 进入到AbstractRefreshableConfigApplicationContext类中,初始化其中的configLocations属性,将传入的configLocations属性赋给它,在赋值的时候还调用了resolvePath方法,由方法名可推断该方法是用来解析路径的,进入该方法
- 里面调用了return getEnvironment().resolveRequiredPlaceholders(path);,首先进入getEnviroment,注意:虽然getEnvironment的调用者是AbstractRefreshableConfigApplicationContext中的resolvePath方法,但getEnvironment方法其实是定义在AbstractApplicationContext中的!
- 里面判断了一下当前环境属性是否为空,此时为true,进入createEnviroment(),并将AbstractApplicationContext类中的environment属性设置为创建的environment!
- createEnvironment做的事情很简单,就是new了一个StandardEnvironment对象
- 进入到StandardEnvironment中,发现其并没有构造器,所以进入其父类AbstractEnvironment去进行初始化操作
- 初始化一些基本属性后,进入到构造方法中的语句,将类中的propertySources属性传入,由属性名我们可以知道该属性包含配置文件相关信息
- 进入该方法后发现该方法通过addLast方法将系统中的相关环境信息加入到了该属性中,但我并不是很清楚该属性是干什么的…好像是用来给子类进行一些扩展操作的?
- 回到resolvePath方法中,该调用resolveRequiredPlaceholders方法了
- 此时进入了AbstractPropertyResolver类解析文件,因为此时还没有相应解析器(上面只创建了PathMatchingResourcePatternResolver路径资源定位器),所以需要创建解析器
- 进入后发现创建的是PropertyPlaceholderHelper对象,由对象名称我们就可以推测该对象是用来帮组解析文件中的占位符的,而且传入的参数很有意思,placeholderPrefix是${,placeholderSuffix是},valueSeparator是:,发现这些参数就是我们配置外部文件时常用的表达式(比如dataSource),继续往下走
- 创建完相应的解析器后,执行doResolvePlaceholders(text, this.strictHelper);,传入配置文件名称和上一步创建的解析器
- 里面调用了解析器的replacePlaceholders方法,结合方法名和上面的参数,resolveRequiredPlaceholders方法实际上完成的操作是将配置文件中的占位符转换为它所代表的真实值,比如将dataSource中的 ${jdbc.driver}转换为其它配置文件中的com.mysql.cj.jdbc.Driver
- 一路返回,setConfigLocations(configLocations);语句执行完毕,总结
- 用传入的configLocations初始化AbstractRefreshableApplicationContext类中的configLocations属性
- 在初始化过程中调用resolvePath方法初步解析配置文件
- 调用AbstractApplicationContext中的getEnvironment方法,初始化环境变量,执行完这一步后,AbstractApplicationContext中的environment就有值了
- 通过resolveRequiredPlaceholders方法将配置文件中的一些占位符转换为真实值(使用PropertyPlaceholderHelper)
- 进入到AbstractRefreshableConfigApplicationContext类中,初始化其中的configLocations属性,将传入的configLocations属性赋给它,在赋值的时候还调用了resolvePath方法,由方法名可推断该方法是用来解析路径的,进入该方法
- refresh(太长了,下一篇博客/(ㄒoㄒ)/~~)
-
super(parent)