背景
在前面的 Lattice – 业务叠加产品 例子中,我们启用的简单模式,在启动Lattice中,我们有下面这个代码:
public static void main(String[] args) {
Lattice.getInstance().setSimpleMode(true);
.......
}
这行代码的作用,是用于Lattice在启动时,自动的进行业务配置的生成并加载到内存中。自动生成配置的代码位置: org.hiforce.lattice.runtime.Lattice#autoBuildBusinessConfig,见下:
private void autoBuildBusinessConfig() {
List<ProductConfig> productConfigs = getAllRegisteredProducts().stream()
.map(this::buildProductConfig)
.collect(Collectors.toList());
for (BusinessSpec businessSpec : getAllRegisteredBusinesses()) {
List<PriorityConfig> priorityConfigs = businessSpec.getRealizations().stream()
.flatMap(p -> autoBuildPriorityConfig(businessSpec, p).stream())
.filter(Objects::nonNull)
.collect(Collectors.toList());
BusinessConfig businessConfig = BusinessConfig.builder()
.bizCode(businessSpec.getCode())
.installedProducts(productConfigs)
.priorityConfigs(priorityConfigs)
.build();
autoMakeupPriorityConfig(businessConfig, getAllRegisteredProducts());
businessConfigs.add(businessConfig);
}
}
一般而言,在开发时用简单模式是比较方便的,但是存在一些隐患:
- 因为在AppStore中,最终会沉淀成百上千个产品插件,并不是每个产品插件,业务都需要安装;自动配置是默认业务需要安装所有产品插件。这会导致一次业务调用中,需要遍历所有产品,并判断产品是否生效,这个会非常耗时;
- 扩展点调用中,如果有多个定制逻辑实现,在FIRST这种Reduce策略下,会对产品优先级非常敏感。 而自动装配的产品,是按照产品自己制定的优先级(默认是500)进行升序排列的(数字越小,优先级越高)。 对于优先级相同情况下,最终排序的结果会和JVM的类加载顺序有关。如果,产品在设计时,没有做好充分的排他性设计,这对于业务执行的确定性,存在重大隐患;
- 如果AppStore中的产品插件,如果是同一个团队提供的,相对比较容易通过 @Product注解中显性申明优先级可以解决。但在多团队合作、生态合作都能参与贡献产品插件情况下,就比较容易产生优先级冲突
- 即使产品做了显性的优先级申明,但实际复杂业务运行中,会发现 A 业务和 B业务对于已安装的两个产品的优先级要求会截然相反,那么这种自动配置方式,就不适用了
所以,在生产环境上,为了业务的确定性,我们可以用代码方式、或者从数据库中读取配置方式,进行业务配置的加载。 这个业务配置,未来是可以做成可视化。 所有人,都能清楚的看到业务的定义如何,这个业务安装了哪些产品插件。 安装的产品在哪些点上会有冲突,这个冲突的优先级是在呢么样的。这对于业务知识的传递、问题排查、生态构建会有极大的帮助。
Step 1: 构建一个无业务配置的调用过程
public class LoadBusinessConfigSample {
public static void main(String[] args) {
Lattice.getInstance().start();
System.out.println("---------------------------------------");
LatticeOverlayProductSample.doBusiness("groupBy");
System.out.println("---------------------------------------");
}
}
因为没有启动简单模式 ,所以上述代码的调用结果如下:
---------------------------------------
Lattice extension invoke error. Due to the business config is null. bizCode: [business.b]
---------------------------------------
Step 2: 为 business.b 构建配置
private static BusinessConfig buildBusinessBConfig() {
return BusinessConfigBuilder.builder()
.bizCode(BusinessB.CODE)
.build();
}
通过BusinessConfig的Builder构造器,我们可以为业务身份为 "business.b” 的业务创建一份配置。
Step 3: 为 business.b 安装 “团购产品”
我们继续修改上面的代码,通过ProductConfigBuilder为业务安装产品插件,如下:
private static BusinessConfig buildBusinessBConfig() {
return BusinessConfigBuilder.builder()
.bizCode(BusinessB.CODE)
.install(GroupBuyProduct.CODE)
.build();
}
Step 4: 为冲突的扩展点指定优先级(即调用顺序)
在我们的样例中,“自定义商品单价”扩展点,是存在多份业务定制实现的,是有冲突的。这里,我们可以指定优先级,让产品的优先级更高。这样,但产品处于生效状态下,那么产品的定制逻辑会优先被调用。如下:
public class LoadBusinessConfigSample {
public static void main(String[] args) {
Lattice.getInstance().start();
Lattice.getInstance().addBusinessConfig(buildBusinessBConfig());//register business configuration.
System.out.println("---------------------------------------");
LatticeOverlayProductSample.doBusiness("groupBy");
System.out.println("---------------------------------------");
}
private static BusinessConfig buildBusinessBConfig() {
return BusinessConfigBuilder.builder()
.bizCode(BusinessB.CODE)
.install(GroupBuyProduct.CODE)
.extension(
PriorityConfigBuilder.builder()
.extCode(EXT_ORDER_LINE_CUSTOM_UNIT_PRICE)
.priority(GroupBuyProduct.CODE, PRODUCT)
.priority(BusinessB.CODE, BUSINESS)
.build())
.build();
}
}
至此,自主注册一份业务配置的样例就可以执行了,执行结果可以发现是产品优先,结果如下:
---------------------------------------
GroupBuyProduct effect status:true
[Business B] overlay product unit price: 700
---------------------------------------
当然,读者也可以把上面优先级注册地方的顺序改一下,改成 业务的优先级 在 产品的优先级之前,如下:
private static BusinessConfig buildBusinessBConfig() {
//优先级调整一下看看效果!
return BusinessConfigBuilder.builder()
.bizCode(BusinessB.CODE)
.install(GroupBuyProduct.CODE)
.extension(
PriorityConfigBuilder.builder()
.extCode(EXT_ORDER_LINE_CUSTOM_UNIT_PRICE)
.priority(BusinessB.CODE, BUSINESS)
.priority(GroupBuyProduct.CODE, PRODUCT)
.build())
.build();
}
再次执行本样例,执行结果会变成:
---------------------------------------
GroupBuyProduct effect status:true
[Business B] overlay product unit price: 1000
---------------------------------------
样例代码
样例代码可以通过访问: https://github.com/hiforce/lattice-sample/tree/main/lattice-business-config 获取
2023-03-05 at 上午12:57
666
2023-06-12 at 下午5:34
好像use-case的情况下,优先级不生效,无论是load resource 还是api的方式,只要有use-case的情况下默认都是usecase