静态代码块适合类加载时预热轻量级共享数据,如配置映射、正则Pattern、线程安全对象池等;不可用于依赖容器或耗时操作,应优先选用ServletContextListener、@PostConstruct或Spring Boot的Runner。
静态代码块可以在类加载时执行,适合用来初始化全局、只读或轻量级的共享数据。但要注意:它仅在类第一次被加载时运行一次,且发生在Web应用启动早期(甚至早于ServletContextListener),因此可用于预热部分基础数据,但不适合耗时操作或依赖容器环境的初始化。
静态代码块预热的适用场景
适用于以下类型的数据:
本地缓存的配置项(如枚举映射、常量字典)
轻量级对象池(如SimpleDateFormat的线程安全封装实例)
预编译的正则表达式 Pattern 实例
静态工具类中需提前初始化的内部状态(如 Jackson 的 ObjectMapper 配置)
典型写法与注意事项
在工具类或配置类中定义静态块,例如:
关键提醒:
Apache Tomcat v9.0.5
Apache Tomcat v9.0.5
下载
不要在静态块中访问 ServletContext、DataSource、Spring Bean 等运行时容器资源(它们尚未初始化)
避免 I/O、网络请求、数据库查询等阻塞操作,否则会拖慢应用启动甚至导致超时失败
若使用 Log4j/SLF4J,确保日志框架已在类加载前完成初始化,否则可能静默丢日志
多个类的静态块执行顺序取决于类加载顺序,不可强依赖先后关系
比静态块更可靠的替代方案
对需要容器上下文或较重逻辑的预热,推荐以下方式:
ServletContextListener#contextInitialized()
:Web 容器启动完成、ServletContext 可用后触发,适合加载 Spring 上下文相关资源、初始化连接池、预热缓存等
@PostConstruct(配合Spring Bean)
:在 Bean 创建完成、依赖注入结束后执行,适合基于 Spring 的业务数据预热
Spring Boot 的 ApplicationRunner / CommandLineRunner
:应用上下文完全就绪后执行,支持异步、条件化和错误处理
验证是否生效的小技巧
可在静态块中加入简单输出,并观察 Tomcat 启动日志:
启动时看到对应日志 → 表明类已被加载,静态块执行成功
首次请求时响应明显变快(对比无预热情况)→ 说明数据确实被提前加载到内存
用 JVisualVM 或 JMC 检查堆内对象数量,确认缓存 Map、Pattern 等已存在
public class GlobalCache {
public static final Map STATUS_MAP = new HashMap<>();
public static final Pattern EMAIL_PATTERN = Pattern.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
static {
// 初始化状态映射
STATUS_MAP.put("0", "待处理");
STATUS_MAP.put("1", "已通过");
STATUS_MAP.put("2", "已拒绝");
// 可加日志提示(注意:此时SLF4J可能未就绪,建议用System.out或确保log已初始化)
System.out.println("[GlobalCache] 静态数据预热完成");
}
}
