开发时改了代码没有生效,与重启后 MyBatis 找不到映射,是两类可能相邻的问题:先确认 IDE 把源码编译到运行 classpath,再检查 DevTools 的重启边界和 mapper XML 所在位置。
DevTools 不是直接执行源文件
旧工程通过以下依赖启用开发工具,版本沿用工程的 Boot 依赖管理:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
optional 主要控制依赖的传递性,不是“值为 true 才能热更新”的开关。IDE 编译、运行配置和 classpath 内容才共同决定变更能否被发现。旧记录涉及 IDEA 2019 的自动构建选项;今天的菜单和运行设置不宜按旧截图逐项照搬。
DevTools 重启使用基础与重启两个类加载器。多模块工程出现加载问题时,可以暂时关闭 restart 做对照,再按证据调整类加载器的包含范围。Boot DevTools 说明
mapper-locations 的星号改变了搜索范围
旧工程将 mapper 路径从 classpath: 改为 classpath*: 后恢复。两种写法不能只当成字符差异:当映射散布在多个 classpath 根或依赖 JAR 中时,需要确认资源解析范围。
例如配置:
mybatis:
mapper-locations: classpath*:mapper/**/*.xml
它假设工程实际按这个目录放置 XML。先检查构建目录和 JAR,再检查加载到的资源 URL;更大的扫描范围也可能带来重复映射。
可在开发诊断代码中观察匹配结果:
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
public class MapperResources {
public static void main(String[] args) throws Exception {
Resource[] resources = new PathMatchingResourcePatternResolver()
.getResources("classpath*:mapper/**/*.xml");
for (Resource resource : resources) {
System.out.println(resource.getURL());
}
}
}
资源解析器的 classpath*: 语义见Spring Resource 文档。
“应用已经停止”不能只靠改资源表达式解决
旧日志还出现过停止后的 Web 应用无法加载资源的提示。这类信息也可能来自旧线程、定时任务或其他对象仍持有旧类加载器。扫描路径正确,不等于重启生命周期就正确。
确认修复时,既要检查 mapper XML 被找到、namespace 与方法匹配,也要观察重复重启后旧线程是否结束。逐层做对照,才能区分“资源没有打包”“扫描范围不对”和“旧上下文仍被访问”。