1. 概览
在各大框架中,延迟加载是一种重要的性能优化手段,所依赖的数据按需逐步完成加载(比如 Hibernate 的延迟加载)。一来,避免了全部加载带来的性能损失;二来,降低业务人员频繁进行 null 判断 和 手工加载的工作量;
1.1. 背景
在微内核架构中,有一个重要的组件 “Context”,作为一个容器,它贯穿于整个处理流程,为各个插件提供数据和服务的共享。
微内核架构示意如下:
微内核架构
有一种典型场景,比如,Plugin-A 和 Plugin-a 在不同流程分支中都使用到了 User 这个对象,通常情况下两个插件都会这样写:
User user = null;
if(context.getUser() == nll){
// 自己进行加载
user = userRepository.getByUserId(context.getUserId());
context.setUser(user);
}else{
// 直接使用其他组件已经加载的数据,避免重复加载
user = context.getUser();
}
其中,重复逻辑如下:
-
首先,判断 context 中是否存在 user 对象;
-
如果不存在,则从 仓库 里获取,并写回到 context,以便后续流程直接使用;
-
如果存在,则直接使用;
由于流程的动态性,难以保障在自己使用时, user 已经被其他组件完成了加载,为了避免 npe 自己不得不重新做一遍。
那结果就是:
-
到处都是重复代码,不便于维护;
-
散弹式修改,加载逻辑变化,修改点过于分散;
-
与业务逻辑耦合在一起,重点不够突出;
-
研发被细节羁绊,无法将精力放到核心逻辑上;
1.2. 目标
问题很明显,解决方案也很清晰,期望能实现:
-
支持延迟加载,在调用时进行自动加载;
-
支持数据缓存,避免数据的多次加载;
-
支持级联加载,所需数据尚未加载,则自动触发依赖数据的加载;
2. 快速入门
2.1. 添加 starter
在 Spring boot 项目的 pom 中增加如下依赖:
<dependency>
<groupId>com.geekhalo.lego</groupId>
<artifactId>lego-starter-loader</artifactId>
<version>0.1.1</version>
</dependency&