静态块加载资源文件的典型写法是声明static properties或map,在static{}中用classloader.getresourceasstream()一次性加载配置,但热部署时不会重执行,导致配置无法自动更新。

静态块加载资源文件的典型写法
静态块在类首次被加载时执行一次,适合做一次性初始化操作,比如读取配置文件到静态变量中。常见做法是声明一个static Properties或static Map,再在static{}里完成加载:
- 先定义静态变量:static Properties config = new Properties();
- 再在静态块中加载:static { try { config.load(new FileInputStream("app.properties")); } catch (IOException e) { e.printStackTrace(); } }
- 注意:文件路径要确保运行时可访问,推荐用ClassLoader.getResourceAsStream()替代FileInputStream,避免路径硬编码和部署环境差异问题
热部署时静态块不会重复执行
这是关键限制——Spring Boot DevTools 或 Tomcat 的热重启机制,本质是销毁旧类加载器、创建新类加载器并重新加载类。但静态块只在类第一次加载时触发,后续热重载不会再次执行它。
- 如果你修改了app.properties内容,静态块不会自动重读,config对象仍保留旧值
- 即使你改了Java类代码并触发热部署,只要类名没变、类加载器换了,静态块也不会运行第二次
- 这意味着:靠静态块加载的配置,在热部署下是“只读快照”,不是实时绑定
绕过限制的实用方案
想让资源文件变更生效,就得跳出静态块依赖,改用运行时按需加载或监听机制:
- 封装成工具方法:把loadConfig()写成普通静态方法,每次使用前手动调用,或配合定时任务/接口触发刷新
- 用 Spring 的 @ConfigurationProperties + @RefreshScope(需整合 Spring Cloud Config 或 Actuator),支持配置热刷新,不依赖静态块
- 监听文件变化:用WatchService监控配置文件,发现变更后主动调用 reload 方法更新内存变量
- 开发阶段可加个/actuator/refresh端点(配合 spring-boot-starter-actuator),手动触发配置重载
为什么不能靠热部署自动同步静态变量
根本原因在JVM类加载机制:每个类加载器维护自己的一份静态变量副本。热部署启用新类加载器后,旧的config还在老加载器里,新的类里config是空的或默认值,二者不互通。
- 无法通过反射修改其他类加载器里的静态字段
- 强行用自定义类加载器做热替换,也难以安全清理旧静态引用,易引发内存泄漏
- 所以框架如 DevTools 默认不尝试“热替换静态状态”,而是选择重启上下文更稳妥










