StrictMap通过强制校验key唯一性存储MappedStatement,key为namespace.id格式,重复注册时抛出含XML路径的异常,底层委托HashMap实现,旨在启动期Fail-Fast防止SQL覆盖。

MyBatis 源码中 StrictMap 是一个专为 MyBatis 内部设计的线程不安全、强约束型 Map 实现,核心作用是安全、唯一地存储 Mapper 语句(MappedStatement)和缓存对象(Cache)等关键元数据,防止重复注册或命名冲突。
它不是通用容器,而是带校验逻辑的封装,重点在“严格性”——注册同名 key 时会主动报错,而非覆盖或静默忽略。
StrictMap 怎么存 Mapper 语句
MappedStatement(即每个 <select>/<insert> 等标签解析后的完整执行单元)最终被存入 Configuration.mappedStatements 字段,该字段声明为:
public Map<String, MappedStatement> mappedStatements = new StrictMap<>("Mapped Statements collection")
.conflictMessageProducer((savedValue, targetValue) ->
". please check " + savedValue.getResource() + " and " + targetValue.getResource());关键行为如下:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
key 是全限定 ID:格式为
namespace.id,例如"com.example.UserMapper.getUserById"
这个字符串由 XML 的namespace属性和 SQL 标签的id属性拼接而成,必须全局唯一。-
put 时强制校验冲突:
当调用strictMap.put("com.example.UserMapper.getUserById", statement)时:- 若 key 不存在 → 正常插入;
- 若 key 已存在 → 不覆盖,而是触发
conflictMessageProducer,抛出IllegalArgumentException,并附带两个冲突语句所在 XML 文件路径(如UserMapper.xml和BackupUserMapper.xml),便于快速定位重复定义。
内部仍用 HashMap 存储:
StrictMap底层委托给HashMap,但重写了put、putAll等方法,加入冲突检测逻辑。它没有额外维护索引或树结构,性能与 HashMap 基本一致,只是多了“防误写”保护。支持泛型与类型安全提示:
构造时传入描述字符串(如"Mapped Statements collection"),仅用于异常信息,不参与运行逻辑;泛型<String, MappedStatement>由编译器保障类型安全。
为什么不用普通 HashMap?
因为 MyBatis 要求:
- 同一个
namespace.id只能定义一次 SQL; - 多模块、多 jar 包、多配置文件场景下,极易因 copy-paste 或命名疏忽导致重复注册;
- 静默覆盖会引发难以排查的行为异常(比如调用 A 方法却执行了 B 的 SQL);
-
StrictMap在加载阶段就 Fail-Fast,把问题暴露在启动期,而不是运行期。
补充:Cache 也用 StrictMap 存
类似地,Configuration.caches 也是 StrictMap<Cache>,key 是 namespace(如 "com.example.UserMapper"),确保每个 Mapper 接口最多绑定一个二级缓存实例。
不复杂但容易忽略。

















