mybatis源码分析之spring加载mapper.xml文件原理解析

本文详细介绍了MyBatis中Mapper XML文件的四种加载方式,包括基于接口类路径、包路径、resources目录以及Spring配置的加载方法。深入解析了Mapper XML文件的加载原理,从setMapperLocations方法入手,跟踪到buildSqlSessionFactory()方法,分析了configuration、configLocation等关键名词,最后讲解了XMLMapperBuilder如何解析Mapper XML文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们来看看mapper.xml文件的加载方式

第一种:基于mapper接口类具体路径配置

这种情况下,如果是非注解模式的话xml配置文件必须和这个类在同一级目录,且与Mapper类同名。项目结构类似

第二种:基于mapper类所在包的package路径配置

  

其实这算是第一种的一个变种。一个配置mapper类,每次新加删除比较麻烦,直接扫描mapper类所在包。项目结构类似

第三种:把 Mapper 的xml配置文件单独放置到 resources 中

和Mapper 类分开了,mapper接口位置还保持不动

但是mapper.xml被移动到了resources目录

第四种:使用spring配置加载mapper配置

可以看到,是往sqlsessionfactory中注入一系列的属性值。

(以上文章摘抄于https://blog.youkuaiyun.com/tanga842428/article/details/79285957,感谢博主的分享)

通过上面的四种配置方式,我们可以看到,mybatis有个默认潜规则:mapper接口类的名字和mapper.xml的名字是一致的。

基于上面的四种配置,可以引申出很多其他形式的配置,比如使用注解,基于实现原理再实现一遍,你就可开源xxx-mybatis-boot-start.jar类。小编们就是基于第四种实现原理,实现类一套,源码如下:

其中res1 和res2使用一个即可。由于项目架构的性质,我们使用了两个(当然还可以更多,因为mapperlocation是数组)。

铺垫做完了,我们开始今天的主题《mybatis源码分析之mapper.xml文件加载原理解析》

分析源码,关键是找对入口。首先我们来看下setMapperLocations方法的作用(resource对象传入的已经是根据正则表达式匹配到的各个xml文件了

“Set locations of MyBatis mapper files that are going to be merged into the {@code SqlSessionFactory}configuration at runtime.”。大概意思是讲:在系统启动时,这些mapper配置文件会被合并初始化到SqlSessionFactory。接下来我们来看下SqlSessionFactory初始化做了些什么。

本文代码的切入点是bean.getObject()。一路跟踪(bean.getObject()->afterPropertiesSet()->buildSqlSessionFactory()),并会发现,真正做事的是buildSqlSessionFactory(),其作用就是创建一个SqlSessionFactory实例并返回。

该方法源码比较长,不再贴源码,只解释下里面关键名词

configuration 、configLocation: mybatis配置文件,两者只会二选一加载,例如上面示例中的mybatis-config.xml

objectFactory mybatis对象工厂(没用过)

objectWrapperFactory mybatis对象包装类工厂(没用过)

vfs mybatis虚拟文件系统,在应用服务内,提供一个非常简单的方式访问资源(没用过)

            typeAliases 类型别名

            typeHandlers 类型处理器

            typeAliasesPackage 类型别名包路径

plugins 插件类(后续会讲)

typeHandlers 类型处理器

typeHandlersPackage 类型处理器包路径

databaseIdProvider (官方描述MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃)

mapperLocations mapper文件地址


解析一个个mapper.xml文件,放入config,然后返回。下面看看XMLMapperBuilder是怎么解析的

第一步:new XMLMapperBuilder构造类,把xml文件解析成document。xml解析方式

第二步:xmlMapperBuilder.parse()。分析xml中的每个node,转化为对象。下面着重介绍这步

configurationElement方法负责解析mapper节点下的各个子节点,并放入configuration中。回想一下mapper.xml的结构。

我们重点介绍下buildStatementFromContext(context.evalNodes("select|insert|update|delete"))方法,该方法是解析增删改查语句生成MappedStatement,并放入configuration的mappedStatements中,解析失败的放入incompleteStatements失败列表。 注意mappedStatements是一个map,value为MappedStatement,key为什么形式呢。举个例子:如果你的接口类(之前的namespace)是com.org.userMapper,节点id为selectOne的话,该map的id为com.org.userMapper.selectOne。这样保证了不同接口类,可以使用相同名字

至此,mapper.xml的解析完成,我们在看看收尾工作是怎么做的

 

解析失败的记录会死循环处理,那么总的有地方触发处理这处理失败的语句。触发方法如下

该方法注释写到,当所有的mapper.xml文件加载完成,推荐只调用一次该方法,处理这些之前失败的记录。

于是查看该方法的调用栈得到

系统启动完成后,会通过event机制调用一次

 作者也玩公众号,欢迎关注《JAVA之庖丁解牛》

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1xmq4bipwe3yf

### MyBatis无法加载Mapper XML文件的原因分析 当遇到MyBatis无法加载`mapper.xml`的情况时,通常是因为配置不正确或路径设置错误。以下是可能导致此问题的一些常见原因以及解决方案。 #### 配置类路径资源未找到 如果`mybatis-config.xml`中的映射器位置指定有误,则可能会导致找不到对应的XML文件。确保在`mybatis-config.xml`中正确定义了扫描包的位置[^1]: ```xml <mappers> <package name="com.example.mapper"/> </mappers> ``` 对于Spring Boot项目而言,在application.properties 或 application.yml 文件里也需要指明相应的路径: ```properties # application.properties mybatis.mapper-locations=classpath*:mapper/*.xml ``` 或者YAML格式下: ```yaml # application.yml mybatis: mapper-locations: classpath*:mapper/**/*.xml ``` #### Mapper接口XML文件名不符 另一个常见的问题是Mapper接口名称和其关联的`.xml`文件的名字并不匹配。为了使它们能够自动配对,这两个名字应该保持一致(除了扩展名外),并且位于相目录结构内[^3]。 例如,如果有如下Java接口定义: ```java public interface UserMapper { } ``` 那么相对应的地图文件应当命名为 `UserMapper.xml`, 并放置在一级别的resources下的相应子文件夹中。 #### 资源不在编译后的ClassPath范围内 有时开发者会把SQL Map文件放在src/main/resources之外的地方,这会造成打包之后这些文件并没有被打入最终JAR/WAR包内的class path里面去。因此运行期就找不见那些必要的Map文件了。所以要确认所有的`*.xml`都处于项目的resource根目录之下或是被包含进了构建工具(如Maven)所管理的标准输出路径之中[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timy07

创作不易,每一分都是真爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值