Pārlūkot izejas kodu

feature #I9K14C 为process方法提供注入型参数特性

everywhere.z 1 gadu atpakaļ
vecāks
revīzija
295bc0e2c6
29 mainītis faili ar 987 papildinājumiem un 12 dzēšanām
  1. 12 0
      liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowFact.java
  2. 73 6
      liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/DeclComponentProxy.java
  3. 13 1
      liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/MethodWrapBean.java
  4. 47 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/ParameterWrapBean.java
  5. 26 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParameterFactException.java
  6. 17 5
      liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringDeclComponentParser.java
  7. 97 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/ProcessFactELDeclMultiSpringbootTest.java
  8. 43 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/CmpConfig.java
  9. 40 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Company.java
  10. 24 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo1Context.java
  11. 29 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo2Context.java
  12. 32 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo3Context.java
  13. 29 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/TestContext.java
  14. 53 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/User.java
  15. 1 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/processFact/application.properties
  16. 18 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/processFact/flow.xml
  17. 97 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/ProcessFactELDeclSpringbootTest.java
  18. 28 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/ACmp.java
  19. 28 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/BCmp.java
  20. 27 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/CCmp.java
  21. 27 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/DCmp.java
  22. 40 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Company.java
  23. 24 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo1Context.java
  24. 29 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo2Context.java
  25. 32 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo3Context.java
  26. 29 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/TestContext.java
  27. 53 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/User.java
  28. 1 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/processFact/application.properties
  29. 18 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/processFact/flow.xml

+ 12 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowFact.java

@@ -0,0 +1,12 @@
+package com.yomahub.liteflow.annotation;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+@Documented
+@Inherited
+public @interface LiteflowFact {
+
+    String value();
+}

+ 73 - 6
liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/DeclComponentProxy.java

@@ -1,17 +1,24 @@
 package com.yomahub.liteflow.core.proxy;
 
 import cn.hutool.core.exceptions.InvocationTargetRuntimeException;
+import cn.hutool.core.lang.Tuple;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
+import com.ql.util.express.DefaultContext;
+import com.ql.util.express.ExpressRunner;
+import com.ql.util.express.InstructionSet;
 import com.yomahub.liteflow.annotation.LiteflowMethod;
 import com.yomahub.liteflow.annotation.LiteflowRetry;
 import com.yomahub.liteflow.core.NodeComponent;
 import com.yomahub.liteflow.exception.ComponentMethodDefineErrorException;
 import com.yomahub.liteflow.exception.LiteFlowException;
+import com.yomahub.liteflow.exception.ParameterFactException;
 import com.yomahub.liteflow.exception.ProxyException;
+import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.log.LFLog;
 import com.yomahub.liteflow.log.LFLoggerManager;
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.util.SerialsUtil;
 import net.bytebuddy.ByteBuddy;
 import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
@@ -21,7 +28,12 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -112,6 +124,10 @@ public class DeclComponentProxy {
                     .findFirst()
                     .orElse(null);
 
+            if (currentMethodWrapBean == null){
+                throw new ProxyException("currentMethodWrapBean is null");
+            }
+
             // 如果被代理的对象里有此标注标的方法,则调用此被代理的对象里的方法,如果没有,则调用父类里的方法
             // 进行检查,检查被代理的bean里是否第一个参数为NodeComponent这个类型的
             boolean checkFlag = currentMethodWrapBean.getMethod().getParameterTypes().length > 0
@@ -124,13 +140,13 @@ public class DeclComponentProxy {
                 throw new ComponentMethodDefineErrorException(errMsg);
             }
 
+
+            // 这里是针对于参数的处理
+            // 首先需要保证第一个参数是NodeComponent
+            // 其次需要针对于@LiteflowFact做处理
             try {
-                if (args != null && args.length > 0){
-                    Object[] wrapArgs = ArrayUtil.insert(args, 0, proxy);
-                    return ReflectUtil.invoke(declWarpBean.getRawBean(), currentMethodWrapBean.getMethod(), wrapArgs);
-                }else{
-                    return ReflectUtil.invoke(declWarpBean.getRawBean(), currentMethodWrapBean.getMethod(), proxy);
-                }
+                Object[] realArgs = loadMethodParameter(proxy, currentMethodWrapBean);
+                return ReflectUtil.invoke(declWarpBean.getRawBean(), currentMethodWrapBean.getMethod(), realArgs);
             }catch (InvocationTargetRuntimeException e) {
                 InvocationTargetException targetEx = (InvocationTargetException) e.getCause();
                 throw targetEx.getTargetException();
@@ -138,4 +154,55 @@ public class DeclComponentProxy {
         }
 
     }
+
+    private final ExpressRunner expressRunner = new ExpressRunner();
+
+    private Object[] loadMethodParameter(Object proxy, MethodWrapBean methodWrapBean){
+        NodeComponent thisNodeComponent = (NodeComponent) proxy;
+
+        return methodWrapBean.getParameterWrapBeanList().stream().map(parameterWrapBean -> {
+            // 如果参数是NodeComponent,那就返回proxy本身
+            if (parameterWrapBean.getParameterType().isAssignableFrom(NodeComponent.class)) {
+                return proxy;
+            }
+
+            // 如果没有@LiteflowFact标注,那么不处理,直接赋值null
+            if (parameterWrapBean.getFact() == null) {
+                return null;
+            }
+
+            // 把上下文数据转换成map形式的,key为别名,value为上下文
+            Map<String, Object> contextMap = DataBus.getSlot(thisNodeComponent.getSlotIndex()).getContextBeanList().stream().collect(
+                    Collectors.toMap(tuple -> tuple.get(0), tuple -> tuple.get(1))
+            );
+
+            List<String> errorList = new ArrayList<>();
+
+            Object result = null;
+            // 根据表达式去上下文里搜索相匹配的数据
+            for(Map.Entry<String, Object> entry : contextMap.entrySet()){
+                try{
+                    InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(entry.getKey() + "." + parameterWrapBean.getFact().value());
+                    DefaultContext<String, Object> context = new DefaultContext<>();
+                    context.put(entry.getKey(), entry.getValue());
+                    result = expressRunner.execute(instructionSet, context, errorList, false, false);
+                    if (result != null){
+                        break;
+                    }
+                }catch (Exception ignore){}
+            }
+
+            if (result == null){
+                try{
+                    // 如果没有搜到,那么尝试推断表达式是指定的上下文,按照指定上下文的方式去再获取
+                    InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache("contextMap." + parameterWrapBean.getFact().value());
+                    DefaultContext<String, Object> context = new DefaultContext<>();
+                    context.put("contextMap", contextMap);
+                    result = expressRunner.execute(instructionSet, context, errorList, false, false);
+                }catch (Exception ignore){}
+            }
+
+            return result;
+        }).toArray();
+    }
 }

+ 13 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/MethodWrapBean.java

@@ -4,6 +4,7 @@ import com.yomahub.liteflow.annotation.LiteflowMethod;
 import com.yomahub.liteflow.annotation.LiteflowRetry;
 
 import java.lang.reflect.Method;
+import java.util.List;
 
 /**
  * LiteflowMethod的包装类
@@ -18,10 +19,13 @@ public class MethodWrapBean {
 
     private LiteflowRetry liteflowRetry;
 
-    public MethodWrapBean(Method method, LiteflowMethod liteflowMethod, LiteflowRetry liteflowRetry) {
+    private List<ParameterWrapBean> parameterWrapBeanList;
+
+    public MethodWrapBean(Method method, LiteflowMethod liteflowMethod, LiteflowRetry liteflowRetry, List<ParameterWrapBean> parameterWrapBeanList) {
         this.method = method;
         this.liteflowMethod = liteflowMethod;
         this.liteflowRetry = liteflowRetry;
+        this.parameterWrapBeanList = parameterWrapBeanList;
     }
 
     public Method getMethod() {
@@ -47,4 +51,12 @@ public class MethodWrapBean {
     public void setLiteflowRetry(LiteflowRetry liteflowRetry) {
         this.liteflowRetry = liteflowRetry;
     }
+
+    public List<ParameterWrapBean> getParameterWrapBeanList() {
+        return parameterWrapBeanList;
+    }
+
+    public void setParameterWrapBeanList(List<ParameterWrapBean> parameterWrapBeanList) {
+        this.parameterWrapBeanList = parameterWrapBeanList;
+    }
 }

+ 47 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/ParameterWrapBean.java

@@ -0,0 +1,47 @@
+package com.yomahub.liteflow.core.proxy;
+
+import com.yomahub.liteflow.annotation.LiteflowFact;
+
+/**
+ * 声明式的包装类
+ * @author Bryan.Zhang
+ * @since 2.12.1
+ */
+public class ParameterWrapBean {
+
+    private Class<?> parameterType;
+
+    private LiteflowFact fact;
+
+    private int index;
+
+    public ParameterWrapBean(Class<?> parameterType, LiteflowFact fact, int index) {
+        this.parameterType = parameterType;
+        this.fact = fact;
+        this.index = index;
+    }
+
+    public Class<?> getParameterType() {
+        return parameterType;
+    }
+
+    public void setParameterType(Class<?> parameterType) {
+        this.parameterType = parameterType;
+    }
+
+    public LiteflowFact getFact() {
+        return fact;
+    }
+
+    public void setFact(LiteflowFact fact) {
+        this.fact = fact;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+}

+ 26 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParameterFactException.java

@@ -0,0 +1,26 @@
+package com.yomahub.liteflow.exception;
+
+/**
+ * @author Bryan.Zhang
+ */
+public class ParameterFactException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	/** 异常信息 */
+	private String message;
+
+	public ParameterFactException(String message) {
+		this.message = message;
+	}
+
+	@Override
+	public String getMessage() {
+		return message;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+}

+ 17 - 5
liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringDeclComponentParser.java

@@ -1,24 +1,27 @@
 package com.yomahub.liteflow.spi.spring;
 
 import cn.hutool.core.annotation.AnnotationUtil;
+import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
-import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
-import com.yomahub.liteflow.annotation.LiteflowComponent;
-import com.yomahub.liteflow.annotation.LiteflowMethod;
-import com.yomahub.liteflow.annotation.LiteflowRetry;
+import com.yomahub.liteflow.annotation.*;
 import com.yomahub.liteflow.annotation.util.AnnoUtil;
 import com.yomahub.liteflow.core.proxy.DeclWarpBean;
 import com.yomahub.liteflow.core.proxy.MethodWrapBean;
+import com.yomahub.liteflow.core.proxy.ParameterWrapBean;
 import com.yomahub.liteflow.enums.NodeTypeEnum;
 import com.yomahub.liteflow.exception.CmpDefinitionException;
 import com.yomahub.liteflow.spi.DeclComponentParser;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Parameter;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * Spring环境声明式组件解析器实现
@@ -73,7 +76,16 @@ public class SpringDeclComponentParser implements DeclComponentParser {
                 nodeType = liteflowMethod.nodeType();
             }
 
-            return new DeclInfo(currNodeId, currNodeName, nodeType, method.getDeclaringClass(), new MethodWrapBean(method, liteflowMethod, liteflowRetry));
+
+            Parameter[] parameters = method.getParameters();
+            List<ParameterWrapBean> parameterList = IntStream.range(0, parameters.length).boxed().map(index -> {
+                Parameter parameter = parameters[index];
+                return new ParameterWrapBean(parameter.getType(), AnnotationUtil.getAnnotation(parameter, LiteflowFact.class), index);
+            }).collect(Collectors.toList());
+
+
+
+            return new DeclInfo(currNodeId, currNodeName, nodeType, method.getDeclaringClass(), new MethodWrapBean(method, liteflowMethod, liteflowRetry, parameterList));
         }).filter(declInfo -> StrUtil.isNotBlank(declInfo.getNodeId())).collect(Collectors.groupingBy(DeclInfo::getNodeId));
 
         return definitionMap.entrySet().stream().map(entry -> {

+ 97 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/ProcessFactELDeclMultiSpringbootTest.java

@@ -0,0 +1,97 @@
+package com.yomahub.liteflow.test.processFact;
+
+import cn.hutool.core.date.DateUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.test.processFact.context.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+
+/**
+ * process方法上的fact映射参数测试
+ * @author Bryan.Zhang
+ */
+@ExtendWith(SpringExtension.class)
+@TestPropertySource(value = "classpath:/processFact/application.properties")
+@SpringBootTest(classes = ProcessFactELDeclMultiSpringbootTest.class)
+@EnableAutoConfiguration
+@ComponentScan({"com.yomahub.liteflow.test.processFact.cmp"})
+public class ProcessFactELDeclMultiSpringbootTest extends BaseTest {
+
+	@Resource
+	private FlowExecutor flowExecutor;
+
+	// 最基本的情况
+	@Test
+	public void testFact1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", createContext());
+		Assertions.assertTrue(response.isSuccess());
+		TestContext context = response.getContextBean(TestContext.class);
+		Assertions.assertEquals("jack", context.getUser().getName());
+	}
+
+	// 多上下文自动搜寻
+	@Test
+	public void testFact2() throws Exception {
+		TestContext testContext = createContext();
+		Demo1Context demo1Context = new Demo1Context();
+		demo1Context.setData1("xxxx");
+		demo1Context.setData2(99);
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg", demo1Context, testContext);
+		Assertions.assertTrue(response.isSuccess());
+		TestContext context = response.getContextBean(TestContext.class);
+		Assertions.assertEquals(20, context.getUser().getCompany().getHeadCount());
+	}
+
+	// 多上下文都有user,指定上下文中的user
+	@Test
+	public void testFact3() throws Exception {
+		TestContext testContext = createContext();
+		Demo2Context demo2Context = createDemo2Context();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg", testContext, demo2Context);
+		Assertions.assertTrue(response.isSuccess());
+		Demo2Context context = response.getContextBean(Demo2Context.class);
+		Assertions.assertEquals("rose", context.getUser().getName());
+	}
+
+	// 多上下文都有user,指定上下文中的user
+	@Test
+	public void testFact4() throws Exception {
+		Demo3Context demo3Context = createDemo3Context();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg", demo3Context);
+		Assertions.assertTrue(response.isSuccess());
+		Demo3Context context = response.getContextBean(Demo3Context.class);
+		Assertions.assertEquals("jelly", context.getUser().getName());
+	}
+
+	private TestContext createContext(){
+		Company company = new Company("XXX有限公司", "黄河路34号303室", 400);
+		User user = new User("张三", 18, DateUtil.parseDate("1990-08-20"), company);
+        return new TestContext(user, "this is data");
+	}
+
+	private Demo2Context createDemo2Context(){
+		Company company = new Company("XXX有限公司", "和平路12号101室", 600);
+		User user = new User("李四", 28, DateUtil.parseDate("1990-06-01"), company);
+		return new Demo2Context("xxx", user);
+	}
+
+	private Demo3Context createDemo3Context(){
+		Company company = new Company("XXX有限公司", "和平路12号101室", 600);
+		User user = new User("王五", 28, DateUtil.parseDate("1990-06-01"), company);
+		return new Demo3Context("xxx", user);
+	}
+
+}

+ 43 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/CmpConfig.java

@@ -0,0 +1,43 @@
+package com.yomahub.liteflow.test.processFact.cmp;
+
+import cn.hutool.core.collection.ConcurrentHashSet;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowFact;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.processFact.context.Company;
+import com.yomahub.liteflow.test.processFact.context.User;
+import org.springframework.stereotype.Component;
+
+@LiteflowComponent
+public class CmpConfig {
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "a")
+    public void processA(NodeComponent bindCmp,
+                        @LiteflowFact("user") User user,
+                        @LiteflowFact("user.company.address") String address) {
+        user.setName("jack");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "b")
+    public void processB(NodeComponent bindCmp,
+                        @LiteflowFact("user.company") Company company,
+                        @LiteflowFact("data2") Integer data) {
+        company.setHeadCount(20);
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "c")
+    public void processC(NodeComponent bindCmp,
+                        @LiteflowFact("demo2Context.user") User user) {
+        user.setName("rose");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "d")
+    public void processD(NodeComponent bindCmp,
+                        @LiteflowFact("ctx.user") User user) {
+        user.setName("jelly");
+    }
+}

+ 40 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Company.java

@@ -0,0 +1,40 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class Company {
+
+    private String name;
+
+    private String address;
+
+    private int headCount;
+
+    public Company(String name, String address, int headCount) {
+        this.name = name;
+        this.address = address;
+        this.headCount = headCount;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public int getHeadCount() {
+        return headCount;
+    }
+
+    public void setHeadCount(int headCount) {
+        this.headCount = headCount;
+    }
+}

+ 24 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo1Context.java

@@ -0,0 +1,24 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class Demo1Context {
+
+    private String data1;
+
+    private Integer data2;
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+
+    public Integer getData2() {
+        return data2;
+    }
+
+    public void setData2(Integer data2) {
+        this.data2 = data2;
+    }
+}

+ 29 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo2Context.java

@@ -0,0 +1,29 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class Demo2Context {
+
+    private String data1;
+
+    private User user;
+
+    public Demo2Context(String data1, User user) {
+        this.data1 = data1;
+        this.user = user;
+    }
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+}

+ 32 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo3Context.java

@@ -0,0 +1,32 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+import com.yomahub.liteflow.context.ContextBean;
+
+@ContextBean("ctx")
+public class Demo3Context {
+
+    private String data1;
+
+    private User user;
+
+    public Demo3Context(String data1, User user) {
+        this.data1 = data1;
+        this.user = user;
+    }
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+}

+ 29 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/TestContext.java

@@ -0,0 +1,29 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class TestContext {
+
+    private User user;
+
+    private String data1;
+
+    public TestContext(User user, String data1) {
+        this.user = user;
+        this.data1 = data1;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+}

+ 53 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/User.java

@@ -0,0 +1,53 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+import java.util.Date;
+
+public class User {
+
+    private String name;
+
+    private int age;
+
+    private Date birthday;
+
+    private Company company;
+
+    public User(String name, int age, Date birthday, Company company) {
+        this.name = name;
+        this.age = age;
+        this.birthday = birthday;
+        this.company = company;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    public Company getCompany() {
+        return company;
+    }
+
+    public void setCompany(Company company) {
+        this.company = company;
+    }
+
+    public Date getBirthday() {
+        return birthday;
+    }
+
+    public void setBirthday(Date birthday) {
+        this.birthday = birthday;
+    }
+}

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/processFact/application.properties

@@ -0,0 +1 @@
+liteflow.rule-source=processFact/flow.xml

+ 18 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/processFact/flow.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<flow>
+    <chain name="chain1">
+        THEN(a);
+    </chain>
+
+    <chain name="chain2">
+        THEN(b);
+    </chain>
+
+    <chain name="chain3">
+        THEN(c);
+    </chain>
+
+    <chain name="chain4">
+        THEN(d);
+    </chain>
+</flow>

+ 97 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/ProcessFactELDeclSpringbootTest.java

@@ -0,0 +1,97 @@
+package com.yomahub.liteflow.test.processFact;
+
+import cn.hutool.core.date.DateUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.test.processFact.context.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+
+/**
+ * process方法上的fact映射参数测试
+ * @author Bryan.Zhang
+ */
+@ExtendWith(SpringExtension.class)
+@TestPropertySource(value = "classpath:/processFact/application.properties")
+@SpringBootTest(classes = ProcessFactELDeclSpringbootTest.class)
+@EnableAutoConfiguration
+@ComponentScan({"com.yomahub.liteflow.test.processFact.cmp"})
+public class ProcessFactELDeclSpringbootTest extends BaseTest {
+
+	@Resource
+	private FlowExecutor flowExecutor;
+
+	// 最基本的情况
+	@Test
+	public void testFact1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", createContext());
+		Assertions.assertTrue(response.isSuccess());
+		TestContext context = response.getContextBean(TestContext.class);
+		Assertions.assertEquals("jack", context.getUser().getName());
+	}
+
+	// 多上下文自动搜寻
+	@Test
+	public void testFact2() throws Exception {
+		TestContext testContext = createContext();
+		Demo1Context demo1Context = new Demo1Context();
+		demo1Context.setData1("xxxx");
+		demo1Context.setData2(99);
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg", demo1Context, testContext);
+		Assertions.assertTrue(response.isSuccess());
+		TestContext context = response.getContextBean(TestContext.class);
+		Assertions.assertEquals(20, context.getUser().getCompany().getHeadCount());
+	}
+
+	// 多上下文都有user,指定上下文中的user
+	@Test
+	public void testFact3() throws Exception {
+		TestContext testContext = createContext();
+		Demo2Context demo2Context = createDemo2Context();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg", testContext, demo2Context);
+		Assertions.assertTrue(response.isSuccess());
+		Demo2Context context = response.getContextBean(Demo2Context.class);
+		Assertions.assertEquals("rose", context.getUser().getName());
+	}
+
+	// 多上下文都有user,指定上下文中的user
+	@Test
+	public void testFact4() throws Exception {
+		Demo3Context demo3Context = createDemo3Context();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg", demo3Context);
+		Assertions.assertTrue(response.isSuccess());
+		Demo3Context context = response.getContextBean(Demo3Context.class);
+		Assertions.assertEquals("jelly", context.getUser().getName());
+	}
+
+	private TestContext createContext(){
+		Company company = new Company("XXX有限公司", "黄河路34号303室", 400);
+		User user = new User("张三", 18, DateUtil.parseDate("1990-08-20"), company);
+        return new TestContext(user, "this is data");
+	}
+
+	private Demo2Context createDemo2Context(){
+		Company company = new Company("XXX有限公司", "和平路12号101室", 600);
+		User user = new User("李四", 28, DateUtil.parseDate("1990-06-01"), company);
+		return new Demo2Context("xxx", user);
+	}
+
+	private Demo3Context createDemo3Context(){
+		Company company = new Company("XXX有限公司", "和平路12号101室", 600);
+		User user = new User("王五", 28, DateUtil.parseDate("1990-06-01"), company);
+		return new Demo3Context("xxx", user);
+	}
+
+}

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/ACmp.java

@@ -0,0 +1,28 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.processFact.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowFact;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.test.processFact.context.User;
+import org.springframework.stereotype.Component;
+
+
+@Component("a")
+public class ACmp {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
+	public void process(NodeComponent bindCmp,
+						@LiteflowFact("user") User user,
+						@LiteflowFact("user.company.address") String address) {
+		user.setName("jack");
+	}
+}

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/BCmp.java

@@ -0,0 +1,28 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.processFact.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowFact;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.test.processFact.context.Company;
+import org.springframework.stereotype.Component;
+
+@Component("b")
+public class BCmp {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
+	public void process(NodeComponent bindCmp,
+						@LiteflowFact("user.company") Company company,
+						@LiteflowFact("data2") Integer data) {
+		company.setHeadCount(20);
+	}
+
+}

+ 27 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/CCmp.java

@@ -0,0 +1,27 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.processFact.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowFact;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.test.processFact.context.User;
+import org.springframework.stereotype.Component;
+
+@Component("c")
+public class CCmp {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
+	public void process(NodeComponent bindCmp,
+						@LiteflowFact("demo2Context.user") User user) {
+		user.setName("rose");
+	}
+
+}

+ 27 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/cmp/DCmp.java

@@ -0,0 +1,27 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.processFact.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowFact;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.test.processFact.context.User;
+import org.springframework.stereotype.Component;
+
+@Component("d")
+public class DCmp {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
+	public void process(NodeComponent bindCmp,
+						@LiteflowFact("ctx.user") User user) {
+		user.setName("jelly");
+	}
+
+}

+ 40 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Company.java

@@ -0,0 +1,40 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class Company {
+
+    private String name;
+
+    private String address;
+
+    private int headCount;
+
+    public Company(String name, String address, int headCount) {
+        this.name = name;
+        this.address = address;
+        this.headCount = headCount;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public int getHeadCount() {
+        return headCount;
+    }
+
+    public void setHeadCount(int headCount) {
+        this.headCount = headCount;
+    }
+}

+ 24 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo1Context.java

@@ -0,0 +1,24 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class Demo1Context {
+
+    private String data1;
+
+    private Integer data2;
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+
+    public Integer getData2() {
+        return data2;
+    }
+
+    public void setData2(Integer data2) {
+        this.data2 = data2;
+    }
+}

+ 29 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo2Context.java

@@ -0,0 +1,29 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class Demo2Context {
+
+    private String data1;
+
+    private User user;
+
+    public Demo2Context(String data1, User user) {
+        this.data1 = data1;
+        this.user = user;
+    }
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+}

+ 32 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/Demo3Context.java

@@ -0,0 +1,32 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+import com.yomahub.liteflow.context.ContextBean;
+
+@ContextBean("ctx")
+public class Demo3Context {
+
+    private String data1;
+
+    private User user;
+
+    public Demo3Context(String data1, User user) {
+        this.data1 = data1;
+        this.user = user;
+    }
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+}

+ 29 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/TestContext.java

@@ -0,0 +1,29 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+public class TestContext {
+
+    private User user;
+
+    private String data1;
+
+    public TestContext(User user, String data1) {
+        this.user = user;
+        this.data1 = data1;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+
+    public String getData1() {
+        return data1;
+    }
+
+    public void setData1(String data1) {
+        this.data1 = data1;
+    }
+}

+ 53 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/processFact/context/User.java

@@ -0,0 +1,53 @@
+package com.yomahub.liteflow.test.processFact.context;
+
+import java.util.Date;
+
+public class User {
+
+    private String name;
+
+    private int age;
+
+    private Date birthday;
+
+    private Company company;
+
+    public User(String name, int age, Date birthday, Company company) {
+        this.name = name;
+        this.age = age;
+        this.birthday = birthday;
+        this.company = company;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    public Company getCompany() {
+        return company;
+    }
+
+    public void setCompany(Company company) {
+        this.company = company;
+    }
+
+    public Date getBirthday() {
+        return birthday;
+    }
+
+    public void setBirthday(Date birthday) {
+        this.birthday = birthday;
+    }
+}

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/processFact/application.properties

@@ -0,0 +1 @@
+liteflow.rule-source=processFact/flow.xml

+ 18 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/processFact/flow.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<flow>
+    <chain name="chain1">
+        THEN(a);
+    </chain>
+
+    <chain name="chain2">
+        THEN(b);
+    </chain>
+
+    <chain name="chain3">
+        THEN(c);
+    </chain>
+
+    <chain name="chain4">
+        THEN(d);
+    </chain>
+</flow>