MyBatis中Configuration的mappedStatements字段为private final Map,需通过反射获取,常见来源是SqlSessionFactory.getConfiguration(),反射步骤包括获取字段、设为可访问、再读取值,但生产环境应优先使用getMappedStatementNames()等官方API。

在 MyBatis 中,Configuration 对象维护了所有已注册的 MappedStatement(即每个 <select>/<update> 等标签解析后的执行单元),但其内部字段 mappedStatements 是私有的(类型为 Map<String, MappedStatement>),默认不提供公开 getter。若需通过反射获取,需绕过访问限制。
确认 Configuration 实例来源
反射操作前,必须先拿到有效的 Configuration 实例。常见来源包括:
- 从
SqlSessionFactory获取:sqlSessionFactory.getConfiguration() - 在
Interceptor中,通过Invocation.getTarget()是Executor或StatementHandler时,可向上获取Configuration - 测试中直接 new SqlSessionFactoryBuilder().build(inputStream).getConfiguration()
使用反射读取 mappedStatements 字段
mappedStatements 在 MyBatis 3.4+ 版本中是 final 修饰的 Map,字段名未变更,位于 org.apache.ibatis.session.Configuration 类中。反射步骤如下:
- 通过
Class.getDeclaredField("mappedStatements")获取字段 - 调用
setAccessible(true)跳过 Java 访问控制检查 - 用
field.get(configuration)获取实际 Map 实例
示例代码:
立即学习“Java免费学习笔记(深入)”;
Configuration configuration = sqlSessionFactory.getConfiguration();
try {
Field field = Configuration.class.getDeclaredField("mappedStatements");
field.setAccessible(true);
Map<String, MappedStatement> statements = (Map<String, MappedStatement>) field.get(configuration);
statements.forEach((id, ms) ->
System.out.println("ID: " + id + ", SQL: " + ms.getBoundSql(null).getSql())
);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
注意兼容性与替代方案
反射方式强依赖 MyBatis 内部实现,存在版本风险:
- MyBatis 3.4.x 至 3.5.x 中字段名稳定为
mappedStatements;3.6+ 未变更,但仍建议在启动时校验字段是否存在 - 生产环境慎用,优先考虑官方支持方式:如通过
configuration.getMappedStatement(String statementId)按需获取单个语句 - 若需遍历全部,可用
configuration.getMappedStatementNames()(返回Collection<String>)配合循环调用getMappedStatement
扩展:获取未加载的 XML 映射语句?
注意:mappedStatements 仅包含已被解析并注册的语句。若某 XML 文件未被 <mappers> 引入或未触发加载(如懒加载未触发),它不会出现在该 Map 中。反射无法“发现”未注册的语句,只能看到当前运行时已加载的全量集合。


















