1 Star 2 Fork 1

付鹏展 / PlaneProgram

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

[TOC]

PlaneProgram 面向平面编程

1.介绍

1.1 目标

1.提高程序阅读性 
2.快速理解程序逻辑

1.2解决的问题、目标、程序设计

​ 一、很多程序逻辑的调用非常的深,比如方法一层层的调用,就会增加程序阅读的复杂度。而且随着阅读的代码越多,进入的方法层数越多,则就需要更强的记忆力,花费额外的时间去帮助记忆。

​ 二、程序员在学习新技术、或者是新业务时,都需要去阅读他人的程序。面对成千上万行的程序代码,即使有丰富的注释,也需要花费很多的时间,才能将整个程序的结构以及细节了解清楚。而面向平面编程可以将所有的注释,按照程序的结构进行组装(还是在程序不运行的情况下)。由此,你可以想象到,程序生成的逻辑就像一篇作文,你只需要阅读完,就清除了解到整个程序的所有逻辑及细节。如果需要立马去优化这段程序,你也知道该去处理哪段程序。而不需要通读完所有程序,才敢下手。

​ 三、面向平面编程,其实是将每段程序都看成一个代码块。比如:当你突然发现成千上万行的程序突然运行缓慢时,你需要去定位具体影响性能的地方时,这可能就会对你造成困扰。而面向平面编程,只需要很简单的写一个代码块代理类(计算程序运行时间),注册后,再运行这段程序,你就能看到所有代码块运行的时间。也就可以直接定位到问题。

​ 面向平面编程的设计:如同xy轴坐标图,y轴即:从上到下展示程序执行顺序,x轴即:从左至右展示程序执行结构,比如分支、循环。同时利用函数式编程,将代码块用Lamda书写,使程序结构简化。

1.3 maven依赖

<dependency>
    <groupId>io.gitee.fpzhan</groupId>
    <artifactId>PlaneProgram</artifactId>
    <version>1.0.1</version>
</dependency>

2.代码块三要素

2.1代码块

任意行数的代码都可以写成一个代码块。

关于代码块大小的建议:能用一句话表达清楚代码块的大致逻辑,不要太抽象,也不要太简单。

代码块的定义如下:

/**
*代码块的定义,入参为Param对象,无出参。可以将返回的参数放入Param,即可在别的代码块中取出,并使用。
*Param 对象内维护了一个Map<String,Object>集合,可以把他当Map对象来使用。
*key:参数名   value:具体的参数对象
*/
@FunctionalInterface
public interface CodeBlockFunction extends Serializable {
    
    Param apply(Param param) throws Exception;

}

2.2 参数

每个代码块,都必须标记参数的变化。

参数变化必然符合以下三种情况:

​ 1.删除参数

​ 2.新增参数

​ 3.无新增无删除

代码块的具体参数为什么重要?

​ 因为程序本质就是数据的处理,通过对数据的操作,来达到目标。而一段程序中,某个变量何时新增,何时删除,与代码块一起绑定。便能帮助代码阅读者,快速定位阅读范围。别忘了,平面编程的目的,就是为了提高程序的阅读性!

如何知道每个代码块,修改了哪些变量?

(下个版本会提供内置的这个功能)程序员可以开发一个代码块运行代理类。通过对比入参前后,对象字节的变化,标记出当前代码块变化的参数。

2.3 注释

​ 平面编程的目的,就是提高程序阅读性。所以注释是必不可少的。

每个代码块,都必须写对应的注释。

​ 平面编程,最后会按照整个程序的结构,将注释组装起来。直接阅读程序的完整逻辑。

2.4 三要素示例

代码:

/*execute(代码块).lose(损失参数).add(新增参数).comment(注释)*/
/*创建流程时,默认会使用一个运行代理类‘检查代码变化,name=[ProxyName.CHECK_PARAM_PROXY]’,如果代码块中参数变化的情况,与后面lose、add标记情况不同,就会报错。当然也可以不使用这个运行代理类。可以参照第七章,环境建议。*/
execute(param -> param.put("one",1)).addc("one").comment("添加变量【one】")

3.效果展示

3.1代码示例

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<String, Object> data = result.getData();
        System.out.println(result.getData().toString());
        //获取流程代理结果
        JSONArray proxyResult = result.getProxyResult();
    }
}

3.2 生成注释

[{
		"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 流程创建

/*创建流程名称为studentFlow的代码流*/
RunFlow runFlow = PlaneProgramManager.createFlow("studentFlow");

4.2 初始化流程参数

//参数
Map map = new HashMap<>();

/*初始化流程参数*/
runFlow.initParam(map)

4.3 创建流程

 /*创建流程*/
 /*创建流程可以创建多个部分,flowBegin不传参,默认为当前流程第一部分*/
runFlow.flowBegin()
    .flowEnd();

4.4 创建分组流程

/*创建流程第一部分*/
runFlow.flowBegin()
    .flowEnd();

/*创建流程第四部分*/
runFlow.flowBegin(3)
    .flowEnd();

/*创建流程第二部分*/
runFlow.flowBegin(1)
    .flowEnd();

/*创建流程第三部分*/
runFlow.flowBegin(2)
    .flowEnd();

/*四个部分,会按照flowBegin内的参数,按照顺序组装。flowBegin(),默认值为0*/

4.5 顺序结构

代码示例:

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();

注释结构:

[{
		"Comment": "对参数无改动"
	},
	{
		"Comment": "添加var变量"
	},
	{
		"Comment": "删除var变量"
	}
]

4.6 作用域结构

介绍:

作用域相当于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();

注释结构:

[
	{
		"Comment":"代码作用域",
		"Scope":[
			{
				"Comment":"添加变量【one】"
			},
			{
				"Comment":"添加变量【two】"
			},
			{
				"Comment":"添加变量【three】"
			}
		]
	},
	{
		"Comment":"作用域内创建的变量,在退出作用域后。会被销毁"
	}
]

4.7 循环结构

注意:

**loop()loopEnd()之间存在作用域。在loop()loopEnd()之间添加到param里的参数,会在loopEnd()**之后被删除。

代码示例:

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();

注释结构:

[{
		"Comment": "添加list变量"
	},
	{
		"Comment": "循环list变量",
		"Loop-flow": [{
			"Comment": "打印元素"
		}]
	}
]

4.8 分支结构

注意:

**branch()branchEnd()之间存在作用域。在branch()branchEnd()之间添加到param里的参数,会在branchEnd()**之后被删除。

代码示例:

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();

注释结构:

[{
		"Comment": "评价"
	},
	{
		"Comment": "判断是否美味",
		"Branch-1": {
			"Comment": "美味",
			"Flow": [{
				"Comment": "夸奖"
			}]
		},
		"Branch-2": {
			"Comment": "不美味",
			"Flow": [{
				"Comment": "批评"
			}]
		}
	}
]

4.9 单分支结构

注意:

aloneBranch()和**aloneBranchEnd()之间存在作用域。在aloneBranch()aloneBranchEnd()之间添加到param里的参数,会在aloneBranchEnd()**之后被删除。

代码示例:

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();

注释结构:

[
	{
		"Comment":"评价"
	},
	{
		"Comment":"如果美味",
		"Branch-1":{
			"Comment":"如果美味",
			"Flow":[
				{
					"Comment":"夸奖"
				}
			]
		}
	}
]

4.10 try-catch结构

注意:

trys()和**catchs()之间存在作用域。在trys()catchs()之间添加到param里的参数,会在catchs()**之后被删除。

**catchs()内存在作用域。如果在catchs()内添加到param里的参数,会在catchs()**之后被删除。

代码示例:

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();

注释结构:

[
	{
		"Comment":"文件处理异常捕获",
		"Try":[
			{
				"Comment":"删除文件!"
			}
		],
		"Catch":[
			{
				"Comment":"文件未找到"
			},
			{
				"Comment":"其他异常"
			}
		]
	}
]

4.11 try-catch-finnally结构

注意:

**finallys()内存在作用域。如果在finallys()内添加到param里的参数,会在finallys()**之后被删除。

代码示例:

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();

注释结构:

[
	{
		"Comment":"文件处理异常捕获",
		"Try":[
			{
				"Comment":"删除文件!"
			}
		],
		"Catch":[
			{
				"Comment":"文件未找到"
			},
			{
				"Comment":"其他异常"
			}
		],
		"Finally":{
			"Comment":"删除后创建"
		}
	}
]

4.12 运行流程

/*运行流程*/
RunResult result = runFlow.run();
/*获取流程结果*/
Map<String,Object> data = result.getData();
/*流程代理结果*/
JSONArray proxyResult = result.getProxyResult();

5 参数工具API

5.1 参数工具介绍

参数工具:优雅的生成关于参数处理的代码块,针对当前流程的某一个参数进行处理的代码块逻辑。

参数工具类:fpzhan.plane.program.param.Params

5.2 新增参数

代码块写法:

runFlow .flowBegin()
    		.execute(param -> param.put("list",new ArrayList<>())).addc("list").comment("新增ArrayList变量")
    	.flowEnd();

(与上面逻辑一致)参数工具:

runFlow .flowBegin()
        	.execute(Params.get(ArrayList::new).add("list")).comment("新增ArrayList变量")
        .flowEnd();

5.3 删除参数

代码块写法:

runFlow .flowBegin()
        	.execute(param -> param.remove("list")).losec("list").comment("删除list变量")
        .flowEnd();

(与上面逻辑一致)参数工具:

runFlow .flowBegin()
        	.execute(Params.lose("list")).comment("删除list变量")
        .flowEnd();

5.4 修改参数

5.4.1 修改参数,引用普通值

代码块写法:

runFlow .flowBegin()
        	.execute(param -> param.get("list",ArrayList.class).add("one")).none().comment("list变量添加元素one")
        .flowEnd();

(与上面逻辑一致)参数工具:

runFlow .flowBegin()
        	.execute(Params.get("list",ArrayList.class).update(ArrayList::add,"one")).comment("list变量添加元素one")
        .flowEnd();

5.4.2 修改参数,引用变量值

代码块写法:

runFlow .flowBegin()
        	.execute(param -> param.get("class", ClassInfos.class).getaClass().setClassName(param.get("className",String.class))).none().comment("将classInfo变量中class属性的className属性,设置为className变量")
        .flowEnd();

(与上面逻辑一致)参数工具:

runFlow .flowBegin()
            .execute(Params.get("class",ClassInfos.class).then(ClassInfos::getaClass).updateLink(AClass::setClassName,"str")).comment("将classInfo变量中class属性的className属性,设置为className变量")
        .flowEnd();

5.5 循环参数中的变量

/*ClassInfos 对象中 students 属性是List对象*/
runFlow .flowBegin()
        	.loop(Params.loop("class", ClassInfos.class).then(ClassInfos::getStudents).element("students")).comment("循环班级里的所有学生")
        .flowEnd();

5.6 循环外部的参数

//循环对象必须实现Collection接口
runFlow .flowBegin()
            .loop(Params.loop(()-> Arrays.asList(new String[]{})).element("elements")).comment("循环班级里的所有学生")
        .flowEnd();

5.7 分支判断

代码块写法:

runFlow .flowBegin()
            .aloneBranch(param -> param.get("class", ClassInfos.class).getStudents().isEmpty()).comment("如果班级没有学生")
                .execute(param -> System.out.println("Enroll new students")).none().comment("招生")
            .aloneBranchEnd()
        .flowEnd();

(与上面逻辑一致)参数工具:

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 内置的组装代理类

/*以4.5代码示例,创建流程*/
/*执行组装代理类*/
JSONArray struct = runFlow.struct();
/*打印组装代理类结果*/
System.out.println(JSON.toJSONString(struct, SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat));

组装代理类结果:

[{
		"Comment": "对参数无改动"
	},
	{
		"Comment": "添加var变量"
	},
	{
		"Comment": "删除var变量"
	}
]

6.1.3 新建自定义的组装代理类

新建自定义组装代理类:

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;
    }
}

使用方式:

/*注册组装代理类*/
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));

组装代理类结果:

[{
		"Comment": "对参数无改动"
	},
	{
		"Comment": "添加var变量"
	},
	{
		"Comment": "删除var变量"
	}
]

6.2 运行代理类

6.2.1 运行代理类介绍

运行代理类:面向平面编程,由代码块组成,在运行时按照结构进行运行。代码块为面向平面编程最小粒度。运行代理类,可以实现在运行时,代理每个代码块,实现对每个代码块运行时的监控。

6.2.2 内置的运行代理类

/*以4.5代码示例,创建流程*/
/*运行流程*/
RunResult result = runFlow.run();
/*打印代理结果*/
System.out.println(JSON.toJSONString(result.getProxyResult(), SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat));

运行代理类结果:

[
	{
		"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 新建自定义的运行代理类

新建自定义的运行代理类

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<String> 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<String> keys, JSONObject json) throws Exception {
        json.put("afterTime",sdf.format(new Date()));
    }
}

使用方式:

/*注册运行代理类*/
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));
 

运行代理类结果:

[
	{
		"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 开发环境

建议:

开发环境可以使用一个组装代理类和所有的运行代理类,以保证程序中所有代码块与标记的情况一致。

/*注册自定义的运行代理类*/
PlaneProgramManager.registerProxy(new TestProxy("runTime",3));
/*使用三个运行代理类,检查参数,运行速度,运行时间[自定义代理类]*/
PlaneProgramManager.useProxy(ProxyName.CHECK_PARAM_PROXY,ProxyName.SPEED_PROXY,"runTime");
//一定要在创建流程之前使用

7.3 生产环境

建议:

生产环境可以不使用任何的组装代理类和运行代理类。这样流程逻辑只包含所有代码块的逻辑,使面向平面编程不会影响到任何程序性能的问题。

//不使用任何运行代理类
PlaneProgramManager.useProxy();
//不使用任何组装代理类
PlaneProgramManager.useStruct(null);
//一定要在创建流程之前使用
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

面向平面编程 展开 收起
Java
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/fpzhan/PlaneProgram.git
git@gitee.com:fpzhan/PlaneProgram.git
fpzhan
PlaneProgram
PlaneProgram
1.0.1

搜索帮助