深色模式
6.3 通过延迟加载数据优化性能
在实际开发中,我们有时希望优化数据集合的获取逻辑(比如从数据库查询数据)——只有当这些集合确实要被使用时,才执行获取操作。
INFO
这种优化思路其实适用于任意类型的数据,但考虑到内存中集合可能占用较大空间,“延迟加载待遍历的集合”是最常见的应用场景。
要实现延迟加载,需让上下文变量实现 ILazyContextVariable 接口(通常继承其默认实现类 LazyContextVariable),数据的实际加载逻辑写在 loadValue() 方法中——这个方法仅在模板首次使用该变量时才会执行。
java
// 将 "users" 变量设为延迟加载,仅在模板使用时才执行数据库查询
context.setVariable(
"users",
new LazyContextVariable<List<User>>() {
@Override
protected List<User> loadValue() {
// 实际的数据获取逻辑(如数据库查询)
return databaseRepository.findAllUsers();
}
});延迟加载的变量在模板中使用时,无需感知其“延迟”特性,用法和普通变量完全一致:
html
<!-- 正常遍历延迟加载的 users 集合 -->
<ul>
<li th:each="u : ${users}" th:text="${u.name}">user name</li>
</ul>如果变量被 th:if 等条件包裹,且条件为 false,则 loadValue() 方法永远不会执行,数据库查询也不会触发:
html
<!-- 当 ${condition} 为 false 时,<ul> 不会渲染,users 的 loadValue() 也不会执行 -->
<ul th:if="${condition}">
<li th:each="u : ${users}" th:text="${u.name}">user name</li>
</ul>关键说明
- 透明使用:模板端无需修改任何代码,延迟加载对模板是完全透明的;
- 执行时机:
loadValue()仅在变量首次被模板访问时执行一次,后续访问会复用已加载的数据; - 适用场景:
- 数据查询成本高(如复杂数据库查询、远程接口调用);
- 变量的使用依赖条件判断(如仅在特定权限/场景下显示数据);
- 集合数据量大,避免不必要的内存占用。
扩展示例(Spring 集成场景)
在 Spring + Thymeleaf 项目中,也可结合 Spring 的懒加载特性简化写法:
java
// Spring 环境下更简洁的写法(借助 Lambda)
context.setVariable("products", (LazyContextVariable<List<Product>>) () ->
productRepository.findAll()
);总结
- Thymeleaf 的延迟加载变量(
LazyContextVariable)能让数据仅在模板实际使用时才执行加载逻辑,避免无效的数据库/远程调用; - 实现方式是继承
LazyContextVariable并重写loadValue(),模板端使用方式与普通变量完全一致; - 核心价值:在变量使用受条件控制时,避免不必要的性能损耗,尤其适合大数据集合、高成本查询的场景。
