Spring的XML解析原理,这一次全搞懂再走
推荐学习
- 肝了十天半月 , 献上纯手绘“Spring/Cloud/Boot/MVC”全家桶脑图
- 疯狂膜拜!阿里出品Spring Security王者晋级文档
文章插图
前言Spring已经是我们Java Web开发必不可少的一个框架 , 其大大简化了我们的开发 , 提高了开发者的效率 。 同时 , 其源码对于开发者来说也是宝藏 , 从中我们可以学习到非常优秀的设计思想以及优雅的命名规范 , 但因其体系庞大、设计复杂对于刚开始阅读源码的人来说是非常困难的 。 所以在此之前首先你得下定决心 , 不管有多困难都得坚持下去;其次 , 最好先把设计模式掌握熟练;然后在开始阅读源码时一定要多画UML类图和时序图 , 多问自己为什么要这么设计?这样设计的好处是什么?还有没有更好的设计?当然 , 晕车是难免的 , 但还是那句话 , 一定要持之以恒(PS:源码版本5.1.3.RELEASE) 。
正文熟悉IOC体系结构要学习Spring源码 , 我们首先得要找准入口 , 那这个入口怎么找呢?我们不妨先思考一下 , 在Spring项目启动时 , Spring做了哪些事情 。 这里我以最原始的xml配置方式来分析 , 那么在项目启动时 , 首先肯定要先定位——找到xml配置文件 , 定位之后肯定是加载——将我们的配置加载到内存 , 最后才是根据我们的配置实例化(本篇文章只讲前两个过程) 。 那么Spring是如何定位和加载xml文件的呢?涉及到哪些类呢?我们先来看张类图:
文章插图
该图是IOC的体系图 , 整体上你需要有一个大概的印象 , 可以看到所有的IOC都是有继承关系的 , 这样设计的好处就是任何一个子类IOC可以直接使用父类IOC加载的Bean , 有点像JVM类加载的双亲委派机制;而红色方框圈起来的是本篇涉及到的重要类 , 需要着重记忆它们的关系 。 图中最重要的两个类是BeanFactory和ApplicationContext , 这是所有IOC的父接口 。 其中BeanFactory提供了最基本的对bean的操作:
文章插图
而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);}} }
然后解析传入的相对路径保存到configLocations变量中 , 最后再调用父类AbstractApplicationContext的refresh方法刷新容器(启动容器都会调用该方法) , 我们着重来看这个方法: public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//为容器初始化做准备prepareRefresh();// 解析xmlConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}} }
- 小米科技|性价比拉满!TCL T8E-PRO QLED智屏当属潮玩世代的必备单品
- 华为鸿蒙系统|华为汽车战略布局,进入汽车行业的底气来自哪里?(车车佳)
- 浙江省|浙江的五大富豪,四位做过中国首富,仅马云的阿里就1年纳税366亿
- iOS|恒创科技:Linux日本云服务器安全设置的基本步骤
- javascript|手机移动端的PyTorch来了,还支持JavaScript
- 中关村|柳传志在这里被骗、掘金,书写半部科技史的中关村经历了什么?
- 手机维修|手机维修的猫腻‖你是不是上当了?
- 智能化|感知局限下,车路协同的“子弹”还得再飞会儿
- 华为鸿蒙系统|都2021年底了,为何Mate40Pro还是目前公认最好用的“安卓”手机
- saas|上半年的Redmi K40 Pro,现在入手2500元不到,还等?