一、前言
Mybatis 全局配置可以通过 XML 构建,也可以编写 Java 代码实现。因为 Mybatis 使用 Configuration 对象保存解析后的信息。
Mybatis 的 org.apache.ibatis.session.Configuration
的对象承载太多的配置信息。比如:
还有很多,就不一一列举。
下面进行 Mybatis 关于配置文件解析。以下分析只贴最核心的源码,至于里面的解析细节,待有余力之际再做分析吧。
二、解析核心代码
2.1 解析 Properties 元素
2.2 别名注册器
根据标签值 type
获取 Class 信息,并调用 typeAliasRegistry.registerAlias
注册 API 添加别名映射相关信息。
2.3 拦截器
2.4 解析 Environment
在这里通过配置信息实例化事务工厂 TransactionFactory
以及数据源 DataSource
。并作为入参通过 build()
方法构建 Environment
。
2.5 类型处理器
2.6 解析 Mapper
2.6.1 ResultMap 解析
ResultMap 解析比较复杂,根据 XML 配置文件构建 ResultMapping 对象。解析结果如下
对象字段映射
<resultMap id="BaseResultMap" type="blog">
<id column="bid" property="bid" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="author_id" property="authorId" jdbcType="INTEGER"/>
</resultMap>
一对多
<resultMap id="BlogWithCommentMap" type="BlogAndComment" extends="BaseResultMap" >
<collection property="comment" ofType="com.domain.Comment">
<id column="comment_id" property="commentId" />
<result column="content" property="content" />
</collection>
</resultMap
2.6.2 解析 select|insert|update|delete XML 标签
增、删、改、查等 XML 元素会被解析为 org.apache.ibatis.mapping.MappedStatement
对象,并将解析后的对象放入 Configuration
Mybatis 配置类中。
2.6.3 解析 SqlSource
SqlSource
解析是非常重要,这一步是在 org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode()
方法内触发解析,
最终由 XMLScriptBuilder#parseScriptNode()
完成解析。
通过源码简单分析解析流程:
#1 触发 SQL 解析动作
参数 context
是 XNode
类型对象,内部包含 XML 定义的信息。createSqlSource()
方法会创建 XMLScriptBuilder
,并用它完成解析动作。
#2 XMLScriptBuilder
parseDynamicTags()
是完成 SQL 解析的核心方法。
#3 SqlNode 节点解析
我们可以从一条在 XML 定义的 foreach 语句看看最终解释出来的对象是什么:
由上图可知,我们在 XML 所定义的一条 SQL 语句被分段解析成三个对象,分别是
StaticTextSqlNode
ForEachSqlNode
StaticTextSqlNode
它们分别存储其中一段 SQL 内容。select * from blog where bid in
这段内部没有占位符,所以是属性静态文本,不需要做任何改动,但是 <foreach>
就不一样了,他需要遍历入参,所以不同 SqlNode
会根据自身条件对应相应的解析动作。而这个解析动作就是 SqlNode
接口定义的 apply(DynamicContext)
方法。
SQLNode 继承体系:
SqlNode
的实现类拥有能解析
而与节点所对应的是不同的 NodeHandler
,它属于 XMLScriptBuilder
内部类。
NodeHandler 继承体系:
SqlNode
节点的创建是由 NodeHandler
完成。
显然,经过以上处理器解析到的 SqlSource
对象,而 SqlSource
也有不同的类型。
SqlSource 继承体系:
Mybatis 一般在 DynamicSqlSource
和 RawSqlSource
做选择,源码如下:
至此,我们简单通过源码了解了 SqlSource
创建过程,从它又引出了 Mybatis 自定义标签(如 <where>
、<trim>
等等)的解析过程。
小结
- XML SQL 解析是在程序启动时完成,使用
MixedSqlNode
封装已解析的SqlNode
对象,并把SqlSource
对象添加到MappedStatement
对象中,后续我们可以直接通过getBoundSql(Object)
获取真实可执行的 SQL 语句。 我们也可以实现自定义的XML/注解解析器。详见
三、总结
Mybatis 配置解析是由
org.apache.ibatis.builder.xml.XMLMapperBuilder
完成的。- Mybatis 可以通过配置类改变 Mybatis 运行时行为。
- 配置类的解析包含Mapper文件的解析。
- Mapper 文件解析
ResultMap
会以namespace
+ id 为 key 值放入配置类Configuration
的resultMaps
Map集合。SELECT|INSERT|DELETE|UPDATE
类型标签被解析为MappedStatement
对象并放入配置类Configuration
的mappedStatements
Map集合对象。key 同样为 namespace + id。
Configuration
这个类非常重要,它包含了 Mybatis 所有信息。SqlSessionFactory
会话工厂会根据该配置类创建SqlSession
连接会话。