# PlaneProgram **Repository Path**: fpzhan/PlaneProgram ## Basic Information - **Project Name**: PlaneProgram - **Description**: 面向平面编程 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: 1.0.1 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2021-10-13 - **Last Updated**: 2021-11-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: PlaneProgram ## README [TOC] # PlaneProgram 面向平面编程 ## 1.介绍 ### 1.1 目标 ```txt 1.提高程序阅读性 2.快速理解程序逻辑 ``` ### 1.2解决的问题、目标、程序设计 ​ 一、很多程序逻辑的调用非常的深,比如方法一层层的调用,就会增加程序阅读的复杂度。而且随着阅读的代码越多,进入的方法层数越多,则就需要更强的记忆力,花费额外的时间去帮助记忆。 ​ 二、程序员在学习新技术、或者是新业务时,都需要去阅读他人的程序。面对成千上万行的程序代码,即使有丰富的注释,也需要花费很多的时间,才能将整个程序的结构以及细节了解清楚。而面向平面编程可以将所有的注释,按照程序的结构进行组装(还是在程序不运行的情况下)。由此,你可以想象到,程序生成的逻辑就像一篇作文,你只需要阅读完,就清除了解到整个程序的所有逻辑及细节。如果需要立马去优化这段程序,你也知道该去处理哪段程序。而不需要通读完所有程序,才敢下手。 ​ 三、面向平面编程,其实是将每段程序都看成一个代码块。比如:当你突然发现成千上万行的程序突然运行缓慢时,你需要去定位具体影响性能的地方时,这可能就会对你造成困扰。而面向平面编程,只需要很简单的写一个代码块代理类(计算程序运行时间),注册后,再运行这段程序,你就能看到所有代码块运行的时间。也就可以直接定位到问题。 ​ 面向平面编程的设计:如同xy轴坐标图,y轴即:从上到下展示程序执行顺序,x轴即:从左至右展示程序执行结构,比如分支、循环。同时利用函数式编程,将代码块用Lamda书写,使程序结构简化。 ​ ### 1.3 maven依赖 ```xml io.gitee.fpzhan PlaneProgram 1.0.1 ``` ## 2.代码块三要素 ### 2.1代码块 **任意行数的代码都可以写成一个代码块。** ***关于代码块大小的建议:能用一句话表达清楚代码块的大致逻辑,不要太抽象,也不要太简单。*** 代码块的定义如下: ```java /** *代码块的定义,入参为Param对象,无出参。可以将返回的参数放入Param,即可在别的代码块中取出,并使用。 *Param 对象内维护了一个Map集合,可以把他当Map对象来使用。 *key:参数名 value:具体的参数对象 */ @FunctionalInterface public interface CodeBlockFunction extends Serializable { Param apply(Param param) throws Exception; } ``` ### 2.2 参数 **每个代码块,都必须标记参数的变化。** 参数变化必然符合以下三种情况: ​ 1.删除参数 ​ 2.新增参数 ​ 3.无新增无删除 ***代码块的具体参数为什么重要?*** ​ 因为程序本质就是数据的处理,通过对数据的操作,来达到目标。而一段程序中,某个变量何时新增,何时删除,与代码块一起绑定。便能帮助代码阅读者,快速定位阅读范围。别忘了,平面编程的目的,就是为了提高程序的阅读性! ***如何知道每个代码块,修改了哪些变量?*** (下个版本会提供内置的这个功能)程序员可以开发一个代码块运行代理类。通过对比入参前后,对象字节的变化,标记出当前代码块变化的参数。 ### 2.3 注释 ​ 平面编程的目的,就是提高程序阅读性。所以注释是必不可少的。 ​ **每个代码块,都必须写对应的注释。** ​ 平面编程,最后会按照整个程序的结构,将注释组装起来。直接阅读程序的完整逻辑。 ### 2.4 三要素示例 代码: ```java /*execute(代码块).lose(损失参数).add(新增参数).comment(注释)*/ /*创建流程时,默认会使用一个运行代理类‘检查代码变化,name=[ProxyName.CHECK_PARAM_PROXY]’,如果代码块中参数变化的情况,与后面lose、add标记情况不同,就会报错。当然也可以不使用这个运行代理类。可以参照第七章,环境建议。*/ execute(param -> param.put("one",1)).addc("one").comment("添加变量【one】") ``` ## 3.效果展示 ### 3.1代码示例 ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.serializer.SerializerFeature; import RunFlow; import RunResult; import PlaneProgramManager; import Params; import fpzhan.plane.program.test.school.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ProcessTest4 { public static RunFlow createFlow() throws Exception { Map map = new HashMap<>(); map.put("class", new AClass("1", "1")); RunFlow runFlow = PlaneProgramManager.createFlow("studentFlow"); runFlow.initParam(map).add("class").comment("初始化参数为,一年级一班信息") .flowBegin() .execute(Params.get(ClassInfos::new).add("classInfo")).comment("创建【班级基础信息】") .execute(param -> param.put("schoolName", "实验小学")).lose().add("schoolName").comment("设置【学校名称】") .execute(Params.get(ArrayList::new).add("women")).comment("创建【班级女生集合】") .execute(Params.get(ArrayList::new).add("men")).comment("创建【班级男生集合】") .execute(Params.get("class", AClass.class).then(Query::teacherByClass).add("teachers")).comment("查询并设置【班级所有老师】") .loop("teachers", "teacher").comment("遍历获取每个老师,分管学生") .execute(Params.get("teacher", Teacher.class).then(Query::studentByTeacher).add("teacherStudents")).comment("查询老师所有学生") .loop("teacherStudents", "student").comment("遍历老师的所有学生,并放入不同性别的的学生集合中") .branch().comment("判断性别") .ifs(Params.judege("student", Student.class).then(Student::isMan).compare(Object::equals, true)).comment("如果是男生") .execute(Params.get("men", List.class).updateLink(List::add, "student")).comment("将当前学生信息放入【班级男生集合】") .exitIfs() .defaults().comment("如果是女生") .execute(Params.get("women", List.class).updateLink(List::add, "student")).comment("将当前学生信息放入【班级女生集合】") .exitDefaults() .branchEnd() .loopEnd() .loopEnd() .execute( Params.get("classInfo", ClassInfos.class) .updateLink(ClassInfos::setTeachers, "teachers") .updateLink(ClassInfos::setMen, "men") .updateLink(ClassInfos::setWomen, "women") ).comment("将【班级老师】、【班级男生】、【班级女生】放入【班级信息】中") .flowEnd(); return runFlow; } public static void main(String[] args) throws Exception { //创建流程 RunFlow runFlow = createFlow(); //不用运行流程,就可以打印流程结构 System.out.println(JSON.toJSONString(runFlow.struct(), SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat)); //运行流程 RunResult result = runFlow.run(); //获取流程结果并打印 Map data = result.getData(); System.out.println(result.getData().toString()); //获取流程代理结果 JSONArray proxyResult = result.getProxyResult(); } } ``` ### 3.2 生成注释 ```json [{ "Comment": "初始化参数为,一年级一班信息" }, { "Comment": "创建【班级基础信息】" }, { "Comment": "创建【班级女生集合】" }, { "Comment": "创建【班级男生集合】" }, { "Comment": "查询并设置【班级所有老师】" }, { "Comment": "遍历获取每个老师,分管学生", "Loop-flow": [{ "Comment": "查询老师所有学生" }, { "Comment": "遍历老师的所有学生,并放入不同性别的的学生集合中", "Loop-flow": [{ "Comment": "判断性别", "Branch-1": { "Comment": "如果是男生", "Flow": [{ "Comment": "将当前学生信息放入【班级男生集合】" }] }, "Branch-2": { "Comment": "如果是女生", "Flow": [{ "Comment": "将当前学生信息放入【班级女生集合】" }] } }] } ] }, { "Comment": "将【班级老师】、【班级男生】、【班级女生】放入【班级信息】中" } ] ``` ## 4.流程 API ### 4.1 流程创建 ```java /*创建流程名称为studentFlow的代码流*/ RunFlow runFlow = PlaneProgramManager.createFlow("studentFlow"); ``` ### 4.2 初始化流程参数 ```java //参数 Map map = new HashMap<>(); /*初始化流程参数*/ runFlow.initParam(map) ``` ### 4.3 创建流程 ```java /*创建流程*/ /*创建流程可以创建多个部分,flowBegin不传参,默认为当前流程第一部分*/ runFlow.flowBegin() .flowEnd(); ``` ### 4.4 创建分组流程 ```java /*创建流程第一部分*/ runFlow.flowBegin() .flowEnd(); /*创建流程第四部分*/ runFlow.flowBegin(3) .flowEnd(); /*创建流程第二部分*/ runFlow.flowBegin(1) .flowEnd(); /*创建流程第三部分*/ runFlow.flowBegin(2) .flowEnd(); /*四个部分,会按照flowBegin内的参数,按照顺序组装。flowBegin(),默认值为0*/ ``` ### 4.5 顺序结构 代码示例: ```java runFlow .flowBegin() .execute(param -> param).none().comment("对参数无改动") .execute(param -> param.put("var",new ArrayList<>())).addc("var").comment("添加var变量") .execute(param -> param.remove("var")).losec("var").comment("删除var变量") .flowEnd(); ``` 注释结构: ```json [{ "Comment": "对参数无改动" }, { "Comment": "添加var变量" }, { "Comment": "删除var变量" } ] ``` ### 4.6 作用域结构 介绍: 作用域相当于java语法中的{}。例如,定义方法具体的逻辑,是在{}内,当在方法中创建临时变量,退出方法后,临时变量将无法再被调用到。作用域也是如此。 代码示例: ```java runFlow .flowBegin() .scope().comment("代码作用域") .execute(param -> param.put("one",1)).addc("one").comment("添加变量【one】") .execute(param -> param.put("two",2)).addc("two").comment("添加变量【two】") .execute(param -> param.put("three",3)).addc("three").comment("添加变量【three】") .scopeEnd() .execute(param -> System.out.println(param.keySet().size())).none().comment("作用域内创建的变量,在退出作用域后。会被销毁") .flowEnd(); ``` 注释结构: ```json [ { "Comment":"代码作用域", "Scope":[ { "Comment":"添加变量【one】" }, { "Comment":"添加变量【two】" }, { "Comment":"添加变量【three】" } ] }, { "Comment":"作用域内创建的变量,在退出作用域后。会被销毁" } ] ``` ### 4.7 循环结构 注意: **loop()**和**loopEnd()**之间存在作用域。在**loop()**与**loopEnd()**之间添加到param里的参数,会在**loopEnd()**之后被删除。 代码示例: ```java runFlow .flowBegin() .execute(param -> param.put("list", Arrays.asList(new String[]{"ONE"}))).addc("list").comment("添加list变量") .loop("list","element").comment("循环list变量") //循环对象必须实现Collection接口 // .loop(Params.loop("list",List.class).element("element")).comment("循环list变量") 两种loop效果相同 .execute(param -> System.out.println(param.get("element"))).none().comment("打印元素") .loopEnd() .flowEnd(); ``` 注释结构: ```json [{ "Comment": "添加list变量" }, { "Comment": "循环list变量", "Loop-flow": [{ "Comment": "打印元素" }] } ] ``` ### 4.8 分支结构 注意: **branch()**和**branchEnd()**之间存在作用域。在**branch()**与**branchEnd()**之间添加到param里的参数,会在**branchEnd()**之后被删除。 代码示例: ```java runFlow .flowBegin() .execute(param -> param.put("isDelicious",true)).addc("isDelicious").comment("评价") .branch().comment("判断是否美味") .ifs(param -> param.get("isDelicious",Boolean.class)).comment("美味") .execute(param -> System.out.println("很好吃!")).none().comment("夸奖") .exitIfs() .defaults().comment("不美味") .execute(param -> System.out.println("不好吃!")).none().comment("批评") .exitDefaults() .branchEnd() .flowEnd(); ``` 注释结构: ```json [{ "Comment": "评价" }, { "Comment": "判断是否美味", "Branch-1": { "Comment": "美味", "Flow": [{ "Comment": "夸奖" }] }, "Branch-2": { "Comment": "不美味", "Flow": [{ "Comment": "批评" }] } } ] ``` ### 4.9 单分支结构 注意: **aloneBranch**()和**aloneBranchEnd()**之间存在作用域。在**aloneBranch()**与**aloneBranchEnd()**之间添加到param里的参数,会在**aloneBranchEnd()**之后被删除。 代码示例: ```java runFlow .flowBegin() .execute(param -> param.put("isDelicious",true)).addc("isDelicious").comment("评价") .aloneBranch(param -> param.get("isDelicious",boolean.class)).comment("如果美味") .execute(param -> System.out.println("good!")).none().comment("夸奖") .aloneBranchEnd() .flowEnd(); ``` 注释结构: ```json [ { "Comment":"评价" }, { "Comment":"如果美味", "Branch-1":{ "Comment":"如果美味", "Flow":[ { "Comment":"夸奖" } ] } } ] ``` ### 4.10 try-catch结构 注意: **trys**()和**catchs()**之间存在作用域。在**trys()**与**catchs()**之间添加到param里的参数,会在**catchs()**之后被删除。 **catchs()**内存在作用域。如果在**catchs()**内添加到param里的参数,会在**catchs()**之后被删除。 代码示例: ```java runFlow .flowBegin() .trys().comment("文件处理异常捕获") .execute(param -> new File(param.get("fileName").toString()).delete()).none().comment("删除文件!") .catchs(FileNotFoundException.class,param -> System.out.println("文件未找到")).none().comment("文件未找到") .catchs(Exception.class,param -> System.out.println("其他异常")).none().comment("其他异常") .finallys() .flowEnd(); ``` 注释结构: ```json [ { "Comment":"文件处理异常捕获", "Try":[ { "Comment":"删除文件!" } ], "Catch":[ { "Comment":"文件未找到" }, { "Comment":"其他异常" } ] } ] ``` ### 4.11 try-catch-finnally结构 注意: **finallys()**内存在作用域。如果在**finallys()**内添加到param里的参数,会在**finallys()**之后被删除。 代码示例: ```java runFlow.flowBegin() .trys().comment("文件处理异常捕获") .execute(param -> new File(param.get("fileName").toString()).delete()).none().comment("删除文件!") .catchs(FileNotFoundException.class,param -> System.out.println("文件未找到")).none().comment("文件未找到") .catchs(Exception.class,param -> System.out.println("其他异常")).none().comment("其他异常") .finallys(param -> new File(param.get("fileName").toString()).createNewFile()).none().comment("删除后创建") .flowEnd(); ``` 注释结构: ```json [ { "Comment":"文件处理异常捕获", "Try":[ { "Comment":"删除文件!" } ], "Catch":[ { "Comment":"文件未找到" }, { "Comment":"其他异常" } ], "Finally":{ "Comment":"删除后创建" } } ] ``` ### 4.12 运行流程 ```java /*运行流程*/ RunResult result = runFlow.run(); /*获取流程结果*/ Map data = result.getData(); /*流程代理结果*/ JSONArray proxyResult = result.getProxyResult(); ``` ## 5 参数工具API ### 5.1 参数工具介绍 参数工具:优雅的生成关于参数处理的代码块,针对当前流程的某一个参数进行处理的代码块逻辑。 参数工具类:fpzhan.plane.program.param.Params ### 5.2 新增参数 代码块写法: ```java runFlow .flowBegin() .execute(param -> param.put("list",new ArrayList<>())).addc("list").comment("新增ArrayList变量") .flowEnd(); ``` (与上面逻辑一致)参数工具: ```java runFlow .flowBegin() .execute(Params.get(ArrayList::new).add("list")).comment("新增ArrayList变量") .flowEnd(); ``` ### 5.3 删除参数 代码块写法: ```java runFlow .flowBegin() .execute(param -> param.remove("list")).losec("list").comment("删除list变量") .flowEnd(); ``` (与上面逻辑一致)参数工具: ```java runFlow .flowBegin() .execute(Params.lose("list")).comment("删除list变量") .flowEnd(); ``` ### 5.4 修改参数 #### 5.4.1 修改参数,引用普通值 代码块写法: ```java runFlow .flowBegin() .execute(param -> param.get("list",ArrayList.class).add("one")).none().comment("list变量添加元素one") .flowEnd(); ``` (与上面逻辑一致)参数工具: ```java runFlow .flowBegin() .execute(Params.get("list",ArrayList.class).update(ArrayList::add,"one")).comment("list变量添加元素one") .flowEnd(); ``` #### 5.4.2 修改参数,引用变量值 代码块写法: ```java runFlow .flowBegin() .execute(param -> param.get("class", ClassInfos.class).getaClass().setClassName(param.get("className",String.class))).none().comment("将classInfo变量中class属性的className属性,设置为className变量") .flowEnd(); ``` (与上面逻辑一致)参数工具: ```java runFlow .flowBegin() .execute(Params.get("class",ClassInfos.class).then(ClassInfos::getaClass).updateLink(AClass::setClassName,"str")).comment("将classInfo变量中class属性的className属性,设置为className变量") .flowEnd(); ``` ### 5.5 循环参数中的变量 ```java /*ClassInfos 对象中 students 属性是List对象*/ runFlow .flowBegin() .loop(Params.loop("class", ClassInfos.class).then(ClassInfos::getStudents).element("students")).comment("循环班级里的所有学生") .flowEnd(); ``` ### 5.6 循环外部的参数 ```java //循环对象必须实现Collection接口 runFlow .flowBegin() .loop(Params.loop(()-> Arrays.asList(new String[]{})).element("elements")).comment("循环班级里的所有学生") .flowEnd(); ``` ### 5.7 分支判断 代码块写法: ```java runFlow .flowBegin() .aloneBranch(param -> param.get("class", ClassInfos.class).getStudents().isEmpty()).comment("如果班级没有学生") .execute(param -> System.out.println("Enroll new students")).none().comment("招生") .aloneBranchEnd() .flowEnd(); ``` (与上面逻辑一致)参数工具: ```java runFlow .flowBegin() .aloneBranch(Params.judege("class",ClassInfos.class).then(ClassInfos::getStudents).compare(List::isEmpty)).comment("如果班级没有学生") .execute(param -> System.out.println("Enroll new students")).none().comment("招生") .aloneBranchEnd() .flowEnd(); ``` ## 6 高级功能 ### 6.1 组装代理类 #### 6.1.1 组装代理类介绍 组装代理类:面向平面编程,基于lamda表达式进行编程。代码块为一段程序的过程,而要将所有的代码块按照结构进行执行,需要经历一个过程,组装。组装代理类,是在组装时,对每个代码块进行代理。生成完整程序流程时,同样也能生成关于结构的相关信息。 #### 6.1.2 内置的组装代理类 ```java /*以4.5代码示例,创建流程*/ /*执行组装代理类*/ JSONArray struct = runFlow.struct(); /*打印组装代理类结果*/ System.out.println(JSON.toJSONString(struct, SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat)); ``` 组装代理类结果: ```json [{ "Comment": "对参数无改动" }, { "Comment": "添加var变量" }, { "Comment": "删除var变量" } ] ``` #### 6.1.3 新建自定义的组装代理类 新建自定义组装代理类: ```java import com.alibaba.fastjson.JSONObject; import fpzhan.plane.program.compose.ComposeContent; import fpzhan.plane.program.compose.ComposeContext; import fpzhan.plane.program.struct.CodeBlockStruct; /** * 继承CodeBlockStruct抽象类,并重写struct方法 */ public class TestStruct extends CodeBlockStruct { public TestStruct(String name) { super(name); } /** * 组装代理类具体组装逻辑 * @param composeContext 组装上下文 * @param composeContent 组装内容 * @param json 需要被返回json对象(注意:不可更改引用), * @return JSONObject * @throws Exception */ @Override public JSONObject struct(ComposeContext composeContext, ComposeContent composeContent, JSONObject json) throws Exception { json.put("commnet",composeContext.getComment()); return json; } } ``` 使用方式: ```java /*注册组装代理类*/ PlaneProgramManager.registerStruct(new TestStruct("testStruct")); /*使用组装代理类,组装代理类全局只有一个生效,最后使用的会覆盖之前的。该操作必须在创建流程之前完成*/ PlaneProgramManager.useStruct("testStruct"); /*创建流程*/ RunFlow runFlow = PlaneProgramManager.createFlow("studentFlow"); runFlow.initParam(new HashMap<>()).none().comment("参数初始化"); runFlow .flowBegin() .execute(param -> {}).none().comment("对参数无改动") .execute(param -> param.put("var",new ArrayList<>())).addc("var").comment("添加var变量") .execute(param -> param.remove("var")).losec("var").comment("删除var变量") .flowEnd(); /*创建流程结束*/ /*runFlow生成结构*/ JSONArray struct = runFlow.struct(); /*打印结构*/ System.out.println(JSON.toJSONString(struct, SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat)); ``` 组装代理类结果: ```json [{ "Comment": "对参数无改动" }, { "Comment": "添加var变量" }, { "Comment": "删除var变量" } ] ``` ### 6.2 运行代理类 #### 6.2.1 运行代理类介绍 运行代理类:面向平面编程,由代码块组成,在运行时按照结构进行运行。代码块为面向平面编程最小粒度。运行代理类,可以实现在运行时,代理每个代码块,实现对每个代码块运行时的监控。 #### 6.2.2 内置的运行代理类 ```java /*以4.5代码示例,创建流程*/ /*运行流程*/ RunResult result = runFlow.run(); /*打印代理结果*/ System.out.println(JSON.toJSONString(result.getProxyResult(), SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat)); ``` 运行代理类结果: ```json [ { "Before-run-params":"[]", "After-run-params":"[]", "Comment":"参数初始化", "Flow-run-speed":1 }, { "Before-run-params":"[]", "After-run-params":"[]", "Comment":"对参数无改动", "Flow-run-speed":0 }, { "Before-run-params":"[]", "After-run-params":"[var]", "Comment":"添加var变量", "Flow-run-speed":0 }, { "Before-run-params":"[var]", "After-run-params":"[]", "Comment":"删除var变量", "Flow-run-speed":0 } ] ``` #### 6.2.3 新建自定义的运行代理类 新建自定义的运行代理类 ```java import com.alibaba.fastjson.JSONObject; import fpzhan.plane.program.compose.ComposeContent; import fpzhan.plane.program.compose.ComposeContext; import fpzhan.plane.program.proxy.CodeBlockProxy; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Set; /** * 运行前后时间代理类 */ public class TestProxy extends CodeBlockProxy { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); public TestProxy(String proxyName, Integer index) { super(proxyName, index); } /** * 运行前执行的方法 * @param composeContext 组装上下文 * @param composeContent 组装内容 * @param keys 运行后,参数名集合 * @param json 代理结果 * @return JSONObject * @throws Exception */ @Override public JSONObject before(ComposeContext composeContext, ComposeContent composeContent, Set keys, JSONObject json) throws Exception { json.put("beforeTime",sdf.format(new Date())); return null; } /** * 运行后执行的方法 * @param before before方法返回的结果 * @param composeContext 组装上下文 * @param composeContent 组装内容 * @param keys 运行后,参数名集合 * @param json 代理结果 * @throws Exception */ @Override public void after(JSONObject before, ComposeContext composeContext, ComposeContent composeContent, Set keys, JSONObject json) throws Exception { json.put("afterTime",sdf.format(new Date())); } } ``` 使用方式: ```java /*注册运行代理类*/ PlaneProgramManager.registerProxy(new TestProxy("runTime",3)); /*使用运行代理类,运行代理类可以使用多个,都会生效。必须在创建流程之前使用*/ /* ProxyName.SPEED_PROXY 是内置运行代理类,生成代码块运行速度。 ProxyName.CHECK_PARAM_PROXY 是内置运行代理类,是检查参数是否与代码块指定的情况一致 "runTime" 是自定义运行代理类,打印运行前后时间。 调用useProxy时,必须将默认的运行代理类包含在内,不然以后创建的流程,不会再执行这些代理类。 */ PlaneProgramManager.useProxy(ProxyName.CHECK_PARAM_PROXY,ProxyName.SPEED_PROXY,"runTime"); RunFlow runFlow = PlaneProgramManager.createFlow("studentFlow"); runFlow.initParam(new HashMap<>()).none().comment("参数初始化"); runFlow.flowBegin() .execute(param -> {}).none().comment("对参数无改动") .execute(param -> param.put("var",new ArrayList<>())).addc("var").comment("添加var变量") .execute(param -> param.remove("var")).losec("var").comment("删除var变量") .flowEnd(); /*运行流程*/ RunResult result = runFlow.run(); /*打印代理结果*/ System.out.println(JSON.toJSONString(result.getProxyResult(), SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat)); ``` 运行代理类结果: ```json [ { "Before-run-params":"[]", "beforeTime":"2021-11-22 14:09:07.293", "After-run-params":"[]", "Comment":"参数初始化", "Flow-run-speed":2, "afterTime":"2021-11-22 14:09:07.295" }, { "Before-run-params":"[]", "beforeTime":"2021-11-22 14:09:07.295", "After-run-params":"[]", "Comment":"对参数无改动", "Flow-run-speed":1, "afterTime":"2021-11-22 14:09:07.296" }, { "Before-run-params":"[]", "beforeTime":"2021-11-22 14:09:07.296", "After-run-params":"[var]", "Comment":"添加var变量", "Flow-run-speed":0, "afterTime":"2021-11-22 14:09:07.296" }, { "Before-run-params":"[var]", "beforeTime":"2021-11-22 14:09:07.296", "After-run-params":"[]", "Comment":"删除var变量", "Flow-run-speed":0, "afterTime":"2021-11-22 14:09:07.296" } ] ``` ## 7 环境建议 ### 7.1 注册代理类 在任何环境下,都可以将所有开发的自定义代理类和内置代理类注册到PlaneProgramManager管理类中。只要未在PlaneProgramManager.useProxy()或PlaneProgramManager.useStruct()中指定,便不会被使用。 ### 7.2 开发环境 建议: 开发环境可以使用一个组装代理类和所有的运行代理类,以保证程序中所有代码块与标记的情况一致。 ```java /*注册自定义的运行代理类*/ PlaneProgramManager.registerProxy(new TestProxy("runTime",3)); /*使用三个运行代理类,检查参数,运行速度,运行时间[自定义代理类]*/ PlaneProgramManager.useProxy(ProxyName.CHECK_PARAM_PROXY,ProxyName.SPEED_PROXY,"runTime"); //一定要在创建流程之前使用 ``` ### 7.3 生产环境 建议: 生产环境可以不使用任何的组装代理类和运行代理类。这样流程逻辑只包含所有代码块的逻辑,使面向平面编程不会影响到任何程序性能的问题。 ```java //不使用任何运行代理类 PlaneProgramManager.useProxy(); //不使用任何组装代理类 PlaneProgramManager.useStruct(null); //一定要在创建流程之前使用 ```