MyBatis 如何解析 XML 配置文件和 SQL 映射文件
MyBatis 使用 SAX(Simple API for XML)解析器来解析 XML 文件,SAX 是一种基于事件驱动的 XML 解析方式,具有高效、低内存消耗的优点。
MyBatis 主要解析两种类型的 XML 文件:
- 核心配置文件 (mybatis-config.xml): 定义 MyBatis 的全局配置信息,如数据源、事务管理器、类型别名、类型处理器、插件、映射器等。
- SQL 映射文件 (例如 UserMapper.xml): 定义 SQL 语句和映射规则,将 SQL 语句与 Mapper 接口的方法关联起来。
解析过程概述:
-
创建 XMLConfigBuilder (解析核心配置文件):
SqlSessionFactoryBuilder的build()方法会创建一个XMLConfigBuilder对象,用于解析核心配置文件。XMLConfigBuilder内部会创建一个 SAX 解析器 (XMLMapperEntityResolver)。XMLConfigBuilder会解析核心配置文件中的各个元素(<properties>,<settings>,<typeAliases>,<typeHandlers>,<plugins>,<environments>,<mappers>等),并将解析结果存储到Configuration对象中。
-
创建 XMLMapperBuilder (解析 SQL 映射文件):
- 在解析核心配置文件中的
<mappers>元素时,XMLConfigBuilder会为每个 SQL 映射文件创建一个XMLMapperBuilder对象。 XMLMapperBuilder内部也会创建一个 SAX 解析器。XMLMapperBuilder会解析 SQL 映射文件中的各个元素(<mapper>,<select>,<insert>,<update>,<delete>,<resultMap>,<sql>等),并将解析结果转换为MappedStatement对象,并添加到Configuration对象的mappedStatements集合中。
- 在解析核心配置文件中的
-
使用 XPath 解析 XML 元素:
- MyBatis 使用 XPath 表达式来定位和解析 XML 文件中的各个元素。
XMLConfigBuilder和XMLMapperBuilder都使用XPathParser来解析 XPath 表达式。
核心配置文件 (mybatis-config.xml) 解析过程 (XMLConfigBuilder):
-
解析
<properties>元素:- 读取
<properties>标签的resource或url属性,加载外部属性文件。 - 解析
<properties>标签内部的<property>子元素,获取属性名和属性值。 - 将属性存储到
Configuration对象的variables属性中(一个Properties对象)。
- 读取
-
解析
<settings>元素:- 解析
<settings>标签内部的<setting>子元素,获取设置名和设置值。 - 将设置存储到
Configuration对象的相应属性中(例如,cacheEnabled、lazyLoadingEnabled等)。
- 解析
-
解析
<typeAliases>元素:- 解析
<typeAliases>标签内部的<typeAlias>子元素,获取别名和对应的 Java 类型。 - 解析
<typeAliases>标签内部的<package>子元素,扫描指定包下的所有类,并自动生成别名(类名首字母小写)。 - 将别名和类型注册到
Configuration对象的typeAliasRegistry中。
- 解析
-
解析
<typeHandlers>元素:- 解析
<typeHandlers>标签内部的<typeHandler>子元素,获取类型处理器类名(或实例)。 - 解析
<typeHandlers>标签内部的<package>子元素,扫描指定包下的所有类型处理器类。 - 将类型处理器注册到
Configuration对象的typeHandlerRegistry中。
- 解析
-
解析
<objectFactory>元素:- 解析
<objectFactory>的type属性,获取对象工厂实现类。 - 反射创建其实例,并设置到
Configuration对象。
- 解析
-
解析
<plugins>元素:- 解析
<plugins>标签内部的<plugin>子元素,获取插件类的全限定名。 - 创建插件实例,并将插件添加到
Configuration对象的interceptorChain中。
- 解析
-
解析
<environments>元素:- 解析
<environments>标签的default属性,获取默认的环境 ID。 - 解析
<environments>标签内部的<environment>子元素,获取环境 ID、事务管理器配置和数据源配置。 - 根据配置创建
TransactionFactory和DataSourceFactory,并创建相应的Transaction和DataSource实例。 - 将环境配置存储到
Configuration对象的environment属性中。
- 解析
-
解析
<databaseIdProvider>元素:- 解析
<databaseIdProvider>的type属性,获取数据库厂商标识提供类。 - 解析其内部
<property>子元素,获取不同数据库对应的标识。
- 解析
-
解析
<mappers>元素:- 解析
<mappers>标签内部的<mapper>子元素,获取 SQL 映射文件的路径(resource、url或class属性)。 - 解析
<mappers>标签内部的<package>子元素,扫描指定包下的所有 Mapper 接口或 XML 映射文件。 - 对于每个 SQL 映射文件,创建一个
XMLMapperBuilder对象,并调用其parse()方法解析 SQL 映射文件。
- 解析
SQL 映射文件 (例如 UserMapper.xml) 解析过程 (XMLMapperBuilder):
-
解析
<mapper>元素:- 获取
<mapper>标签的namespace属性,作为 Mapper 接口的全限定名。
- 获取
-
解析
<cache>元素(如果有):- 解析
<cache>标签,获取缓存配置信息,创建Cache对象。
- 解析
-
解析
<parameterMap>元素(已废弃,不建议使用):
- 解析
<parameterMap>标签及其子元素,获取参数映射信息。
-
解析
<resultMap>元素:- 解析
<resultMap>标签及其子元素(<id>,<result>,<association>,<collection>,<discriminator>),获取结果映射规则。 - 创建
ResultMap对象,并添加到Configuration对象的resultMaps集合中。
- 解析
-
解析
<sql>元素:- 解析
<sql>标签,获取可重用的 SQL 片段。 - 将 SQL 片段存储到
Configuration对象的sqlFragments集合中。
- 解析
-
解析
<select>,<insert>,<update>,<delete>元素:- 解析这些标签的属性(
id,parameterType,resultType,resultMap,statementType,flushCache,useCache,timeout等)。 - 解析 SQL 语句内容,处理占位符(
#{}和${})。 - 创建
MappedStatement对象,并将 SQL 语句、参数类型、结果类型、SQL 类型(SELECT,INSERT,UPDATE,DELETE)等信息存储到MappedStatement对象中。 - 将
MappedStatement对象添加到Configuration对象的mappedStatements集合中。
- 解析这些标签的属性(
关键类:
XMLConfigBuilder: 负责解析核心配置文件。XMLMapperBuilder: 负责解析 SQL 映射文件。XPathParser: 用于解析 XPath 表达式。Configuration: 保存 MyBatis 的全局配置信息,以及解析后的MappedStatement、ResultMap等对象。MappedStatement: 代表一个 SQL 语句,包含了 SQL 语句的 ID、参数类型、结果类型、SQL 语句内容等信息。ResultMap: 代表一个结果映射规则,定义了如何将查询结果集映射为 Java 对象。
总结:
MyBatis 使用 SAX 解析器和 XPath 表达式来解析 XML 配置文件。XMLConfigBuilder 负责解析核心配置文件,XMLMapperBuilder 负责解析 SQL 映射文件。解析后的配置信息存储在 Configuration 对象中,MappedStatement 对象代表 SQL 语句,ResultMap 对象代表结果映射规则。
