一:场景描述
为了便于阐述我们的使用过程,我们假设有如下的案例:
1.案例参与人员:假设有2家公司:致远,协同云。关系是:协同云是致远的客开公司。
2.场景描述:我们以:cap hr 模块为例:
2.1 致远公司规定:员工年龄必须大于20岁 2.2 协同云公司规定:员工年龄必须大于20岁,并且学历是本科之上-- **在致远公司的规定之上,新增要求:新增学历需求**
- 致远公司代码现状:我们以伪代码讲解
/** * 入职员工入库 */ public Response submit(Person person) { //第一步验证参数 int age= person.getAge(); if (age<20) { throw new RuntimeException("员工年龄必须大于20岁。"); } //第二步:保存入职员工信息 save(person); }
二:名词解释
1.业务组:上述提到的致远公司。
2.客开组:上述提到的协同云。
3.埋点:在标准产品中,我们以接口预先植入“动作”的方式 ,我们叫插庄或者埋点。
如下有代码:
/** * 入职员工入库 */ public Response submit(Person person) { //第一步验证参数 int age= person.getAge(); if (age<20) { throw new RuntimeException("员工年龄必须大于20岁。"); } //第二步:保存入职员工信息 save(person); }
埋点实例:
/** * 入职员工入库 */ public Response submit(Person person) { //第一步验证参数 int age= person.getAge(); if (age<20) { throw new RuntimeException("员工年龄必须大于20岁。"); } //这里就叫埋点: 植入动作。 psersonAnction.check(person); //第二步:保存入职员工信息 save(person); //这里就叫埋点: 植入动作。 doAfterSave(Person); } 说明:**如上所述:埋点的本质是:函数回调。
三:操作步骤
1.第一步:(业务组)业务扩展接口埋点
1.1 引入jar 包
<!-- bean 覆盖包 --> <dependency> <groupId>com.seeyon.infra</groupId> <artifactId>spring-sdk-core</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
说明:引入该jar 包,将自动引入扩展接口关联和bean 替换能力
1.2 创建cap 业务接口父类,并继承:DynamicInterface
如下代码:
package com.seeyon.cap4; import com.seeyon.infra.spring_sdk_core.DynamicInterface; /** * cap 业务模块的动态接口父接口 * 用来划分:接口分类,如cap,会议等 * * @author mt * @date 2021/4/25 */ public interface CapDynamicInterface extends DynamicInterface { /** * cap 业务模块 * * @return */ @Override default String getModuleName() { return "cap"; } /** * cap 业务模块 * * @return */ @Override default String getModuleDes() { return "低码平台接口父接口"; } }
1.3 定义具体的业务接口,并继承:CapDynamicInterface
根据上述场景,我们需要提供在员工保存前,对员工检验动作的扩展接口。
如下代码,我们定义接口名称为:IPersonAction,动作名称为:check 的函数:
package com.seeyon.cap4.form.modules.log; import com.seeyon.cap4.CapDynamicInterface; /** * 扩展接口 * * @author mt */ public interface IPersonAction extends CapDynamicInterface { /** * @return */ void check(Person person); }
说明:所有当前模块下动态接口,一定要继承: CapDynamicInterface ,否则:在接口扫描的时候,会扫描不到该接口
1.4 业务代码植入动作:
如上述:我们已有伪代码如下:
/** * 入职员工入库 */ public Response submit(Person person) { //第一步验证参数 int age= person.getAge(); if (age<20) { throw new RuntimeException("员工年龄必须大于20岁。"); } //第二步:保存入职员工信息 save(person); }
植入步骤1:声明植入动态接口上下文 与 动作接口
/** * 动态bean 上下文 * 必须注入 */ @Inject private DynamicContext dynamicContext; /** * 被植入的对象 * 注入:只声明属性,不能使用@Inject 等注入 */ private IPersonAction personAction = null;
植入步骤2:初始化
/** * 注入扩展接口实现 */
@PostConstruct
public void init() {
personAction = dynamicContext.getBean(IPersonAction.class);
}
植入步骤3:动作调用
/** * 入职员工入库 */ public Response submit(Person person) { //第一步验证参数 int age= person.getAge(); if (age<20) { throw new RuntimeException("员工年龄必须大于20岁。"); } //动作植入,请注意,一定要判断是否有动作植入,业务场景下,很有可能当前动作,我不做修改。所以判null,必然要判断,以保障代码的可靠性。 if (personAction!=null) { personAction.check(person); } //第二步:保存入职员工信息 save(person); }
到此:业务组编码完成。
2.第二步:(业务组)业务接口部署
2.1 打包:将cap 达成jar 包,部署到cap 模块中。
部署路径:\webapps\seeyon\WEB-INF\cfgHome\plugin\cap4\ ,如图:
说明:部署规则。
3 第三步:(客开组)客开实现
3.1 创建项目:如下图:
3.2 pom 引入上述业务埋点的cap:
<dependency> <groupId>com.seeyon</groupId> <artifactId>cap-core</artifactId> <version>trunk-SNAPSHOT</version> </dependency>
3.3 实现业务埋点动作:
如下代码:
package com.seeyon.infra.demo; import com.seeyon.cap4.form.modules.log.IA; import com.seeyon.infra.spring_sdk_core.bean_overrdie.Replace; /** * 协同云实现:员工年龄必须大于20岁,并且学历是本科之上 * @author mt * @date 2021/4/23 */ public class PersonAction implements IPersonAction { @Override public void check(Persion persion) { if(persion!=null) { int edu=persion.getEdu(); if(edu<50) {//假设:50以上,是本科 throw new DynamicBeanException("员工学历必须大于本科。"); } } } }
3.4 以A8 xml 形式注入bean:
我们将此xml 文件,命名为:spring-demo-manager.xml ,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <!--注入bean --> <bean name="personAction" class="com.seeyon.infra.demo.PersonAction"></bean> </beans>
到此整个客开编码结束。
4 第四步:(客开组)客开项目部署
4.1 部署到plugin-kaike 下,如图:
说明:部署规则
四:适用场景
1.适用场景
为了防止不通用场景,造成标准产品代码“膨胀”,由此:扩展接口仅适用于通用场景下的业务。特殊的客开场景,扩展接口无法实现。
那些是通用场景?
由产品经理分析,其后研发实现,并给出扩展接口列表。扩展接口列表覆盖的场景即为扩展接口适用的场景。
五: 标准产品升级与客开升级关注点
1.代码合并成本为零:
由于:整个扩展接口通过jar包的方式,共享能力,分离代码,由此:代码合并成本为零。
同时:通过接口的形式,分离标准产品业务和客开业务,两者业务代码不交叉,由此:标准产品升级不影响客开程序。
2. 标准产品升级(如从1.0.0 升级到2.0.0 ),客开关注点:
客开不需要关注。
3.客开产品升级(如从1.0.0 升级到2.0.0 ),标准产品关注点:
标准产品不需要关注。
4.升级部署
各自独立打包,独立部署。