静态代码块可用于加载配置,但需谨慎使用:仅执行一次、不支持热更新、依赖类路径资源定位、必须处理编码与异常、宜用枚举封装值、避免用于动态配置。

静态代码块确实能用于加载配置,但它不是“自动可靠的配置管家”,而是一个需要谨慎使用的初始化机制。它只执行一次、不随配置变更重运行、对资源路径和异常极其敏感——用对了可简化启动逻辑,用错了会导致类加载失败、参数为空、中文乱码甚至服务起不来。
优先走类路径,别碰相对文件路径
写 new FileInputStream("config.properties") 看似简单,但打包成 JAR 后必然失败,因为工作目录和 classpath 完全不是一回事。必须依赖类加载器定位资源:
- 用
Class.getClassLoader().getResourceAsStream("application.properties"),从 classpath 根目录查找 - 若配置不在 classpath(比如放在
/etc/myapp/),需回退到系统属性指定的绝对路径:System.getProperty("config.path") - 流为
null时不能静默忽略,要明确抛出RuntimeException或提供 fallback 逻辑,避免后续调用返回null引发 NPE
字符编码和异常处理不能省略
Java 8+ 的 Properties.load(InputStream) 默认按 ISO-8859-1 解码,遇到中文键或值直接乱码。同时,IO 异常若只打印堆栈而不中断初始化,可能导致部分字段未赋值就继续执行,让类处于半初始化状态。
- 必须用
load(new InputStreamReader(is, "UTF-8"))显式指定编码 - 所有
getProperty()赋值操作都放在try块内,确保要么全部成功,要么整个静态块失败退出 - 捕获
IOException后建议包装为IllegalStateException并带上下文信息,比如“加载 application.properties 失败:文件不存在或权限不足”
用枚举封装配置值,不只是存字符串
把 status=2 直接赋给 int 变量,既没语义又难校验。静态块配合枚举,能把配置真正变成可验证、可提示、可重构的业务概念。
- 定义枚举时带构造参数,如
PENDING(1), SHIPPED(2), CANCELLED(3) - 静态块中读到
order.status.default=2后,调用OrderStatus.fromCode(2)查找,找不到就抛IllegalArgumentException - 对外暴露的是枚举引用,不是原始数字——数据库查询、接口响应、if 判断全都用
OrderStatus.SHIPPED,IDE 自动补全、编译期检查、全局重命名都受支持
热部署和动态刷新场景下请绕开静态块
Spring Boot DevTools 重启、Tomcat 热加载时,新类由新类加载器加载,静态变量是干净的空值,旧值留在老加载器里,根本不会同步。指望改个 properties 再点 Restart 就生效,是误解机制。
- 开发阶段推荐用
@ConfigurationProperties + @RefreshScope配合/actuator/refresh - 生产环境应放弃静态块托管运行时可变配置,改用监听文件变更后主动 reload 的方案(如
spring-boot-devtools的 production-ready 替代品,或自研 WatchService) - 如果坚持用静态块,只让它加载真正“启动即固定、终身不变”的参数,比如加密盐值、默认连接超时毫秒数、基础 API 版本号
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











