Spring的XML解析原理,这一次全搞懂再走

推荐学习

  • 肝了十天半月 , 献上纯手绘“Spring/Cloud/Boot/MVC”全家桶脑图
  • 疯狂膜拜!阿里出品Spring Security王者晋级文档

Spring的XML解析原理,这一次全搞懂再走文章插图
前言Spring已经是我们Java Web开发必不可少的一个框架 , 其大大简化了我们的开发 , 提高了开发者的效率 。 同时 , 其源码对于开发者来说也是宝藏 , 从中我们可以学习到非常优秀的设计思想以及优雅的命名规范 , 但因其体系庞大、设计复杂对于刚开始阅读源码的人来说是非常困难的 。 所以在此之前首先你得下定决心 , 不管有多困难都得坚持下去;其次 , 最好先把设计模式掌握熟练;然后在开始阅读源码时一定要多画UML类图和时序图 , 多问自己为什么要这么设计?这样设计的好处是什么?还有没有更好的设计?当然 , 晕车是难免的 , 但还是那句话 , 一定要持之以恒(PS:源码版本5.1.3.RELEASE) 。
正文熟悉IOC体系结构要学习Spring源码 , 我们首先得要找准入口 , 那这个入口怎么找呢?我们不妨先思考一下 , 在Spring项目启动时 , Spring做了哪些事情 。 这里我以最原始的xml配置方式来分析 , 那么在项目启动时 , 首先肯定要先定位——找到xml配置文件 , 定位之后肯定是加载——将我们的配置加载到内存 , 最后才是根据我们的配置实例化(本篇文章只讲前两个过程) 。 那么Spring是如何定位和加载xml文件的呢?涉及到哪些类呢?我们先来看张类图:
Spring的XML解析原理,这一次全搞懂再走文章插图
该图是IOC的体系图 , 整体上你需要有一个大概的印象 , 可以看到所有的IOC都是有继承关系的 , 这样设计的好处就是任何一个子类IOC可以直接使用父类IOC加载的Bean , 有点像JVM类加载的双亲委派机制;而红色方框圈起来的是本篇涉及到的重要类 , 需要着重记忆它们的关系 。 图中最重要的两个类是BeanFactory和ApplicationContext , 这是所有IOC的父接口 。 其中BeanFactory提供了最基本的对bean的操作:
Spring的XML解析原理,这一次全搞懂再走文章插图
而ApplicationContex继承了BeanFactory , 同时还继承了MessageSource、ResourceLoader、ApplicationEventPublisher等接口以提供国际化、资源加载、事件发布等高级功能 。 我们应该想到平时Spring加载xml文件应该是ApplicationContext的子类 , 从图中我们可以看到一个叫ClassPathXmlApplicationContext的类 , 联想到我们平时都会 将xml放到classPath下 , 所以我们直接从这个类开始就行 , 这就是优秀命名的好处 。
探究配置加载的过程在ClassPathXmlApplicationContext中有很多构造方法 , 其中有一个是传入一个字符串的(即配置文件的相对路径) , 但最终是调用的下面这个构造:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {super(parent);//创建解析器 , 解析configLocationssetConfigLocations(configLocations);if (refresh) {refresh();} }首先调用父类构造器设置环境:
public AbstractApplicationContext(@Nullable ApplicationContext parent) {this();setParent(parent); }public void setParent(@Nullable ApplicationContext parent) {this.parent = parent;if (parent != null) {Environment parentEnvironment = parent.getEnvironment();if (parentEnvironment instanceof ConfigurableEnvironment) {getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);}} }