这是Configuration里面最后一部分数据的解析,也是最复杂的一部分,所以这里使用了一篇来专门说这个,希望可以尽量说的清除点,首先要先看几个比较重要的概念
mapper
这个就是一个个的文件,大概格式如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zxc.study.test.mapper.UserMapper">
<select id="selectUser" resultType="com.zxc.study.test.bean.User" flushCache="true">
select * from user where id = #{param1}
</select>
<select id="test" resultType="com.zxc.study.test.bean.User">
select * from user where id in
<foreach collection="objectList" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
</mapper>
BoundSql
绑定sql的对象,里面包含了具体的sql执行语句,比如
select * from user where id = ? and name = ?
与对应填充占位符对象ParameterMapping,里面包含了类型等
SqlSource
sql生成来源接口,用来获取BoundSql的源接口,主要有几个实现
DynamicSqlSource:动态sql数据源,也是最核心的一种了
StaticSqlSource:静态sql数据源,直接拿到就行了
RawSqlSource:介于两者之间的
LanguageDriver
语言驱动器,用来获取SqlSource的接口,主要有以下的实现
XMLLanguageDriver:也就是从xml文件解析,就想上面的例子一样
RawLanguageDriver:从接口上的注解进行解析的,比如
@Select("select * from user where id = #{id}")
User a(@Param("id") Integer id);
会从接口上解析select里面的语句出来,不过这种尽量少用比较好
以上是一些比较核心的接口和对应的一些基本类,接下来再去看源码解析是怎么走的
源码解析
解析入口为
org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
//循环处理
for (XNode child : parent.getChildren()) {
//包格式的处理,等同于接口类型的处理
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);
} else {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
//xml文件格式处理
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
InputStream inputStream = Resources.getUrlAsStream(url);
//xml文件格式处理
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url == null && mapperClass != null) {
//接口处理
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
//xml和接口必须要有一个,否则抛异常
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
可以看到实际上有两种解析方法,一种是通过xml,一种是通过接口,不过两种最终都会保存一份到另外一个位置去,比如xml解析完会根据namespace把接口也注册进行,接口注册完也会生成一份xml的进

本文详细解读了Mybatis中XML配置文件的复杂解析过程,涉及mapper接口、BoundSql、SqlSource、LanguageDriver等核心概念,以及XMLMapperBuilder和MapperAnnotationBuilder的解析流程,帮助理解Mybatis内部工作机制。
最低0.47元/天 解锁文章
2883

被折叠的 条评论
为什么被折叠?



