Ver Fonte

feature #I5RV5D 循环表达式特性的增加

everywhere.z há 2 anos atrás
pai
commit
1c2b75e08d
34 ficheiros alterados com 832 adições e 50 exclusões
  1. 10 0
      liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowBreakCmpDefine.java
  2. 10 0
      liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowForCmpDefine.java
  3. 10 0
      liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowWhileCmpDefine.java
  4. 36 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java
  5. 4 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java
  6. 54 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/BreakOperator.java
  7. 50 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java
  8. 46 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java
  9. 36 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhileOperator.java
  10. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
  11. 4 6
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ComponentInitializer.java
  12. 21 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBreakComponent.java
  13. 22 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java
  14. 21 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeWhileComponent.java
  15. 19 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBreakComponent.java
  16. 19 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptForComponent.java
  17. 20 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptWhileComponent.java
  18. 4 1
      liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/ComponentProxy.java
  19. 10 4
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/AnnotationNodeTypeEnum.java
  20. 5 1
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/ConditionTypeEnum.java
  21. 3 0
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java
  22. 65 7
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java
  23. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoForNodeException.java
  24. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoWhileNodeException.java
  25. 57 9
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java
  26. 75 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ForCondition.java
  27. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/IfCondition.java
  28. 23 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/LoopCondition.java
  29. 74 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhileCondition.java
  30. 28 11
      liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java
  31. 30 0
      liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java
  32. 2 0
      liteflow-core/src/main/java/com/yomahub/liteflow/util/LOGOPrinter.java
  33. 21 8
      liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteFlowProxyUtil.java
  34. 1 1
      liteflow-script-plugin/liteflow-script-groovy/src/main/java/com/yomahub/liteflow/script/groovy/GroovyScriptExecutor.java

+ 10 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowBreakCmpDefine.java

@@ -0,0 +1,10 @@
+package com.yomahub.liteflow.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface LiteflowBreakCmpDefine {
+}

+ 10 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowForCmpDefine.java

@@ -0,0 +1,10 @@
+package com.yomahub.liteflow.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface LiteflowForCmpDefine {
+}

+ 10 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowWhileCmpDefine.java

@@ -0,0 +1,10 @@
+package com.yomahub.liteflow.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface LiteflowWhileCmpDefine {
+}

+ 36 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java

@@ -36,6 +36,18 @@ public class LiteFlowNodeBuilder {
         return new LiteFlowNodeBuilder(NodeTypeEnum.IF);
     }
 
+    public static LiteFlowNodeBuilder createForNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.FOR);
+    }
+
+    public static LiteFlowNodeBuilder createWhileNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.WHILE);
+    }
+
+    public static LiteFlowNodeBuilder createBreakNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.BREAK);
+    }
+
     public static LiteFlowNodeBuilder createScriptNode() {
         return new LiteFlowNodeBuilder(NodeTypeEnum.SCRIPT);
     }
@@ -48,6 +60,18 @@ public class LiteFlowNodeBuilder {
         return new LiteFlowNodeBuilder(NodeTypeEnum.IF_SCRIPT);
     }
 
+    public static LiteFlowNodeBuilder createScriptForNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.FOR_SCRIPT);
+    }
+
+    public static LiteFlowNodeBuilder createScriptWhileNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.WHILE_SCRIPT);
+    }
+
+    public static LiteFlowNodeBuilder createScriptBreakNode() {
+        return new LiteFlowNodeBuilder(NodeTypeEnum.BREAK_SCRIPT);
+    }
+
     public LiteFlowNodeBuilder() {
         this.node = new Node();
     }
@@ -114,12 +138,24 @@ public class LiteFlowNodeBuilder {
                 FlowBus.addSwitchNode(this.node.getId(), this.node.getName(), this.node.getClazz());
             } else if (this.node.getType().equals(NodeTypeEnum.IF)) {
                 FlowBus.addIfNode(this.node.getId(), this.node.getName(), this.node.getClazz());
+            } else if (this.node.getType().equals(NodeTypeEnum.FOR)) {
+                FlowBus.addForNode(this.node.getId(), this.node.getName(), this.node.getClazz());
+            } else if (this.node.getType().equals(NodeTypeEnum.WHILE)) {
+                FlowBus.addWhileNode(this.node.getId(), this.node.getName(), this.node.getClazz());
+            } else if (this.node.getType().equals(NodeTypeEnum.BREAK)) {
+                FlowBus.addBreakNode(this.node.getId(), this.node.getName(), this.node.getClazz());
             } else if (this.node.getType().equals(NodeTypeEnum.SCRIPT)) {
                 FlowBus.addCommonScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
             } else if (this.node.getType().equals(NodeTypeEnum.SWITCH_SCRIPT)) {
                 FlowBus.addSwitchScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
             } else if (this.node.getType().equals(NodeTypeEnum.IF_SCRIPT)) {
                 FlowBus.addIfScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
+            } else if (this.node.getType().equals(NodeTypeEnum.FOR_SCRIPT)) {
+                FlowBus.addForScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
+            } else if (this.node.getType().equals(NodeTypeEnum.WHILE_SCRIPT)) {
+                FlowBus.addWhileScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
+            } else if (this.node.getType().equals(NodeTypeEnum.BREAK_SCRIPT)) {
+                FlowBus.addBreakScriptNode(this.node.getId(), this.node.getName(), this.node.getScript());
             }
         } catch (Exception e) {
             String errMsg = StrUtil.format("An exception occurred while building the node[{}],{}", this.node.getId(),e.getMessage());

+ 4 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java

@@ -61,6 +61,10 @@ public class LiteFlowChainELBuilder {
         EXPRESS_RUNNER.addFunctionAndClassMethod("ignoreError", Object.class, new IgnoreErrorOperator());
         EXPRESS_RUNNER.addFunctionAndClassMethod("threadPool", Object.class, new ThreadPoolOperator());
         EXPRESS_RUNNER.addFunction("node", new NodeOperator());
+        EXPRESS_RUNNER.addFunction("FOR", new ForOperator());
+
+        EXPRESS_RUNNER.addFunctionAndClassMethod("DO", Object.class, new DoOperator());
+        EXPRESS_RUNNER.addFunctionAndClassMethod("BREAK", Object.class, new BreakOperator());
     }
 
     public static LiteFlowChainELBuilder createChain() {

+ 54 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/BreakOperator.java

@@ -0,0 +1,54 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.collection.ListUtil;
+import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
+import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.flow.element.condition.Condition;
+import com.yomahub.liteflow.flow.element.condition.ForCondition;
+import com.yomahub.liteflow.flow.element.condition.LoopCondition;
+import com.yomahub.liteflow.flow.element.condition.WhileCondition;
+
+/**
+ * EL规则中的BREAK的操作符
+ * 有两种用法
+ * FOR...DO...BREAK
+ * WHILE...DO...BREAK
+ *
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class BreakOperator extends BaseOperator<LoopCondition> {
+    @Override
+    public LoopCondition build(Object[] objects) throws Exception {
+        OperatorHelper.checkObjectSizeEqTwo(objects);
+
+        //由于BREAK关键字有可能用在FOR后面,也有可能用于WHILE后面,所以这里要进行判断
+        LoopCondition condition;
+        if (objects[0] instanceof ForCondition){
+            //获得caller,也就是ForCondition
+            condition = OperatorHelper.convert(objects[0], ForCondition.class);
+        }else if(objects[0] instanceof WhileCondition){
+            //获得caller,也就是WhileCondition
+            condition = OperatorHelper.convert(objects[0], WhileCondition.class);
+        }else{
+            throw new QLException("The caller must be ForCondition or WhileCondition item");
+        }
+
+        //获得需要执行的可执行表达式
+        if (objects[1] instanceof Node){
+            Node breakNode = OperatorHelper.convert(objects[1], Node.class);
+
+            if (ListUtil.toList(NodeTypeEnum.BREAK, NodeTypeEnum.BREAK_SCRIPT).contains(breakNode.getType())){
+                condition.setBreakNode(breakNode);
+            }else{
+                throw new QLException("The parameter must be node-break item");
+            }
+        }else{
+            throw new QLException("The parameter must be Node item");
+        }
+        return condition;
+    }
+}

+ 50 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java

@@ -0,0 +1,50 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.collection.ListUtil;
+import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
+import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.Condition;
+import com.yomahub.liteflow.flow.element.condition.ForCondition;
+import com.yomahub.liteflow.flow.element.condition.LoopCondition;
+import com.yomahub.liteflow.flow.element.condition.WhileCondition;
+
+/**
+ * EL规则中的DO的操作符
+ * 有两种用法
+ * FOR...DO...BREAK
+ * WHILE...DO...BREAK
+ *
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class DoOperator extends BaseOperator<LoopCondition> {
+    @Override
+    public LoopCondition build(Object[] objects) throws Exception {
+        OperatorHelper.checkObjectSizeEqTwo(objects);
+
+        //由于DO关键字有可能用在FOR后面,也有可能用于WHILE后面,所以这里要进行判断
+        LoopCondition condition;
+        if (objects[0] instanceof ForCondition){
+            //获得caller,也就是ForCondition
+            condition = OperatorHelper.convert(objects[0], ForCondition.class);
+        }else if(objects[0] instanceof WhileCondition){
+            //获得caller,也就是WhileCondition
+            condition = OperatorHelper.convert(objects[0], WhileCondition.class);
+        }else{
+            throw new QLException("The caller must be ForCondition or WhileCondition item");
+        }
+
+        //获得需要执行的可执行表达式
+        if (objects[1] instanceof Executable){
+            Executable doExecutableItem = OperatorHelper.convert(objects[1], Executable.class);
+
+            condition.setExecutableList(ListUtil.toList(doExecutableItem));
+        }else{
+            throw new QLException("The parameter must be Executable item");
+        }
+
+        return condition;
+    }
+}

+ 46 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java

@@ -0,0 +1,46 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.collection.ListUtil;
+import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
+import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
+import com.yomahub.liteflow.core.NodeForComponent;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.flow.element.condition.ForCondition;
+
+/**
+ * EL规则中的FOR的操作符
+ *
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class ForOperator extends BaseOperator<ForCondition> {
+    @Override
+    public ForCondition build(Object[] objects) throws Exception {
+        OperatorHelper.checkObjectSizeEq(objects, 1);
+
+        Node node;
+        if (objects[0] instanceof Node) {
+            node = (Node) objects[0];
+            if (!ListUtil.toList(NodeTypeEnum.FOR, NodeTypeEnum.FOR_SCRIPT).contains(node.getType())) {
+                throw new QLException("The parameter must be for-node item");
+            }
+        }else if(objects[0] instanceof Integer){
+            Integer forCount = (Integer) objects[0];
+            node = new Node();
+            node.setInstance(new NodeForComponent() {
+                @Override
+                public int processFor(){
+                    return forCount;
+                }
+            });
+        }else{
+            throw new QLException("The parameter must be Node item");
+        }
+
+        ForCondition forCondition = new ForCondition();
+        forCondition.setForNode(node);
+        return forCondition;
+    }
+}

+ 36 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhileOperator.java

@@ -0,0 +1,36 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import cn.hutool.core.collection.ListUtil;
+import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
+import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.flow.element.condition.WhileCondition;
+
+/**
+ * EL规则中的WHILE的操作符
+ *
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class WhileOperator extends BaseOperator<WhileCondition> {
+    @Override
+    public WhileCondition build(Object[] objects) throws Exception {
+        OperatorHelper.checkObjectSizeEq(objects, 1);
+
+        Node node;
+        if (objects[0] instanceof Node){
+            node = (Node) objects[0];
+            if (!ListUtil.toList(NodeTypeEnum.WHILE, NodeTypeEnum.WHILE_SCRIPT).contains(node.getType())) {
+                throw new QLException("The parameter must be while-node item");
+            }
+        }else{
+            throw new QLException("The parameter must be Node item");
+        }
+
+        WhileCondition whileCondition = new WhileCondition();
+        whileCondition.setWhileNode(node);
+        return whileCondition;
+    }
+}

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java

@@ -126,7 +126,7 @@ public class OperatorHelper {
             return (T) object;
         }
 
-        throw new QLException("The caller must be " + tClass.getName() + " item");
+        throw new QLException("The parameter must be " + tClass.getName() + " item");
     }
 
     /**

+ 4 - 6
liteflow-core/src/main/java/com/yomahub/liteflow/core/ComponentInitializer.java

@@ -29,7 +29,7 @@ public class ComponentInitializer {
         return instance;
     }
 
-    public NodeComponent initComponent(NodeComponent nodeComponent, NodeTypeEnum type, String desc, String nodeId){
+    public NodeComponent initComponent(NodeComponent nodeComponent, NodeTypeEnum type, String name, String nodeId){
         nodeComponent.setNodeId(nodeId);
         nodeComponent.setSelf(nodeComponent);
         nodeComponent.setType(type);
@@ -42,11 +42,9 @@ public class ComponentInitializer {
 
         //先取传进来的name值(配置文件中配置的),再看有没有配置@LiteflowComponent标注
         //@LiteflowComponent标注只在spring体系下生效,这里用了spi机制取到相应环境下的实现类
-        nodeComponent.setName(desc);
-        if (ListUtil.toList(NodeTypeEnum.COMMON, NodeTypeEnum.SWITCH, NodeTypeEnum.IF).contains(type)
-                && StrUtil.isBlank(nodeComponent.getName())){
-            String name = LiteflowComponentSupportHolder.loadLiteflowComponentSupport().getCmpName(nodeComponent);
-            nodeComponent.setName(name);
+        nodeComponent.setName(name);
+        if (!type.isScript() && StrUtil.isBlank(nodeComponent.getName())){
+            nodeComponent.setName(LiteflowComponentSupportHolder.loadLiteflowComponentSupport().getCmpName(nodeComponent));
         }
 
         //先从组件上取@RetryCount标注,如果没有,则看全局配置,全局配置如果不配置的话,默认是0

+ 21 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBreakComponent.java

@@ -0,0 +1,21 @@
+package com.yomahub.liteflow.core;
+
+import com.yomahub.liteflow.slot.Slot;
+import com.yomahub.liteflow.util.LiteFlowProxyUtil;
+
+/**
+ * 循环跳出节点逻辑抽象类
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public abstract class NodeBreakComponent extends NodeComponent{
+    @Override
+    public void process() throws Exception {
+        boolean breakFlag = processBreak();
+        Slot slot = this.getSlot();
+        Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+        slot.setBreakResult(originalClass.getName(), breakFlag);
+    }
+
+    public abstract boolean processBreak() throws Exception;
+}

+ 22 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java

@@ -0,0 +1,22 @@
+package com.yomahub.liteflow.core;
+
+import com.yomahub.liteflow.slot.Slot;
+import com.yomahub.liteflow.util.LiteFlowProxyUtil;
+
+/**
+ * FOR计数节点抽象类
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public abstract class NodeForComponent extends NodeComponent{
+
+    @Override
+    public void process() throws Exception {
+        int forCount = processFor();
+        Slot slot = this.getSlot();
+        Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+        slot.setForResult(originalClass.getName(), forCount);
+    }
+
+    public abstract int processFor() throws Exception;
+}

+ 21 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeWhileComponent.java

@@ -0,0 +1,21 @@
+package com.yomahub.liteflow.core;
+
+import com.yomahub.liteflow.slot.Slot;
+import com.yomahub.liteflow.util.LiteFlowProxyUtil;
+
+/**
+ * WHILE条件节点抽象类
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public abstract class NodeWhileComponent extends NodeComponent{
+    @Override
+    public void process() throws Exception {
+        boolean whileFlag = processWhile();
+        Slot slot = this.getSlot();
+        Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+        slot.setWhileResult(originalClass.getName(), whileFlag);
+    }
+
+    public abstract boolean processWhile() throws Exception;
+}

+ 19 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBreakComponent.java

@@ -0,0 +1,19 @@
+package com.yomahub.liteflow.core;
+
+import com.yomahub.liteflow.script.ScriptExecutorFactory;
+
+/**
+ * 脚本BREAK节点
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class ScriptBreakComponent extends NodeBreakComponent{
+    @Override
+    public boolean processBreak() throws Exception {
+        return (boolean) ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(this.getCurrChainName(), getNodeId(), getSlotIndex());
+    }
+
+    public void loadScript(String script) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    }
+}

+ 19 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptForComponent.java

@@ -0,0 +1,19 @@
+package com.yomahub.liteflow.core;
+
+import com.yomahub.liteflow.script.ScriptExecutorFactory;
+
+/**
+ * 脚本FOR节点
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class ScriptForComponent extends NodeForComponent{
+    @Override
+    public int processFor() throws Exception {
+        return (int) ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(this.getCurrChainName(), getNodeId(), getSlotIndex());
+    }
+
+    public void loadScript(String script) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    }
+}

+ 20 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptWhileComponent.java

@@ -0,0 +1,20 @@
+package com.yomahub.liteflow.core;
+
+import com.yomahub.liteflow.script.ScriptExecutorFactory;
+
+/**
+ * 脚本WHILE节点
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class ScriptWhileComponent extends NodeWhileComponent{
+
+    @Override
+    public boolean processWhile() throws Exception {
+        return (boolean) ScriptExecutorFactory.loadInstance().getScriptExecutor().execute(this.getCurrChainName(), getNodeId(), getSlotIndex());
+    }
+
+    public void loadScript(String script) {
+        ScriptExecutorFactory.loadInstance().getScriptExecutor().load(getNodeId(), script);
+    }
+}

+ 4 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/core/proxy/ComponentProxy.java

@@ -105,7 +105,10 @@ public class ComponentProxy {
                         boolean existRetry = liteflowRetry != null;
                         boolean isProcess = liteflowMethod.value().equals(LiteFlowMethodEnum.PROCESS)
                                 || liteflowMethod.value().equals(LiteFlowMethodEnum.PROCESS_IF)
-                                || liteflowMethod.value().equals(LiteFlowMethodEnum.PROCESS_SWITCH);
+                                || liteflowMethod.value().equals(LiteFlowMethodEnum.PROCESS_SWITCH)
+                                || liteflowMethod.value().equals(LiteFlowMethodEnum.PROCESS_FOR)
+                                || liteflowMethod.value().equals(LiteFlowMethodEnum.PROCESS_WHILE)
+                                || liteflowMethod.value().equals(LiteFlowMethodEnum.PROCESS_BREAK);
                         // 如果是再Process方法上的liteflowRetry注解,则默认为真实节点。
                         if (isProcess && existRetry) {
                             liteflowRetryAtomicReference.set(liteflowRetry);

+ 10 - 4
liteflow-core/src/main/java/com/yomahub/liteflow/enums/AnnotationNodeTypeEnum.java

@@ -1,8 +1,6 @@
 package com.yomahub.liteflow.enums;
 
-import com.yomahub.liteflow.core.NodeComponent;
-import com.yomahub.liteflow.core.NodeIfComponent;
-import com.yomahub.liteflow.core.NodeSwitchComponent;
+import com.yomahub.liteflow.core.*;
 
 /**
  * 注解节点类型枚举
@@ -22,7 +20,15 @@ public enum AnnotationNodeTypeEnum {
     /**
      * 条件节点
      */
-    IF("条件", NodeIfComponent.class),;
+    IF("条件", NodeIfComponent.class),
+
+    FOR("计数循环",NodeForComponent.class),
+
+    WHILE("条件循环", NodeWhileComponent.class),
+
+    BREAK("跳出循环", NodeBreakComponent.class)
+    ;
+
     /**
      * 描述
      */

+ 5 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/enums/ConditionTypeEnum.java

@@ -7,7 +7,11 @@ public enum ConditionTypeEnum {
 
     TYPE_IF("if", "if"),
     TYPE_PRE("pre","pre"),
-    TYPE_FINALLY("finally","finally")
+    TYPE_FINALLY("finally","finally"),
+
+    TYPE_FOR("for", "for"),
+
+    TYPE_WHILE("while", "while")
     ;
     private String type;
     private String name;

+ 3 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java

@@ -4,6 +4,9 @@ public enum LiteFlowMethodEnum {
     PROCESS("process"),
     PROCESS_SWITCH("processSwitch"),
     PROCESS_IF("processIf"),
+    PROCESS_FOR("processFor"),
+    PROCESS_WHILE("processWhile"),
+    PROCESS_BREAK("processBreak"),
     IS_ACCESS("isAccess"),
 
     IS_END("isEnd"),

+ 65 - 7
liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java

@@ -1,5 +1,8 @@
 package com.yomahub.liteflow.enums;
 
+import cn.hutool.core.util.ClassUtil;
+import com.yomahub.liteflow.core.*;
+
 /**
  * 节点类型枚举
  * @author Bryan.Zhang
@@ -7,22 +10,41 @@ package com.yomahub.liteflow.enums;
  */
 public enum NodeTypeEnum {
 
-    COMMON("common","普通"),
+    COMMON("common","普通", false, NodeComponent.class),
+
+    SWITCH("switch", "选择", false, NodeSwitchComponent.class),
+
+    IF("if", "条件", false, NodeIfComponent.class),
+
+    FOR("for","循环次数", false, NodeForComponent.class),
+
+    WHILE("while", "循环条件", false, NodeWhileComponent.class),
+
+    BREAK("break", "循环跳出", false, NodeBreakComponent.class),
+    SCRIPT("script","脚本", true, ScriptComponent.class),
+
+    SWITCH_SCRIPT("switch_script", "选择脚本", true, ScriptSwitchComponent.class),
+
+    IF_SCRIPT("if_script", "条件脚本", true, ScriptIfComponent.class),
 
-    SWITCH("switch", "选择"),
+    FOR_SCRIPT("for_script", "循环次数脚本", true, ScriptForComponent.class),
 
-    IF("if", "条件"),
-    SCRIPT("script","脚本"),
-    SWITCH_SCRIPT("switch_script","选择脚本"),
+    WHILE_SCRIPT("while_script", "循环条件脚本", true, ScriptWhileComponent.class),
 
-    IF_SCRIPT("if_script", "条件脚本")
+    BREAK_SCRIPT("break_script", "循环跳出脚本", true, ScriptBreakComponent.class)
     ;
     private String code;
     private String name;
 
-    NodeTypeEnum(String code, String name) {
+    private boolean isScript;
+
+    private Class<?> mappingClazz;
+
+    NodeTypeEnum(String code, String name, boolean isScript, Class<?> mappingClazz) {
         this.code = code;
         this.name = name;
+        this.isScript = isScript;
+        this.mappingClazz = mappingClazz;
     }
 
     public String getCode() {
@@ -41,6 +63,22 @@ public enum NodeTypeEnum {
         this.name = name;
     }
 
+    public boolean isScript() {
+        return isScript;
+    }
+
+    public void setScript(boolean script) {
+        isScript = script;
+    }
+
+    public Class<?> getMappingClazz() {
+        return mappingClazz;
+    }
+
+    public void setMappingClazz(Class<?> mappingClazz) {
+        this.mappingClazz = mappingClazz;
+    }
+
     public static NodeTypeEnum getEnumByCode(String code) {
         for (NodeTypeEnum e : NodeTypeEnum.values()) {
             if (e.getCode().equals(code)) {
@@ -49,4 +87,24 @@ public enum NodeTypeEnum {
         }
         return null;
     }
+
+    public static NodeTypeEnum guessTypeByClazz(Class<?> clazz){
+        Class<?> superClazz = clazz;
+        while(true){
+            superClazz = superClazz.getSuperclass();
+            if (superClazz.getPackage().getName().startsWith("com.yomahub.liteflow.core")){
+                break;
+            }
+            if(superClazz.equals(Object.class)){
+                return null;
+            }
+        }
+
+        for (NodeTypeEnum e : NodeTypeEnum.values()) {
+            if (e.getMappingClazz().equals(superClazz)) {
+                return e;
+            }
+        }
+        return null;
+    }
 }

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoForNodeException.java

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

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NoWhileNodeException.java

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

+ 57 - 9
liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java

@@ -86,14 +86,8 @@ public class FlowBus {
     }
 
     public static void addSpringScanNode(String nodeId, NodeComponent nodeComponent) {
-        NodeTypeEnum type = null;
-        if (nodeComponent instanceof NodeSwitchComponent){
-            type = NodeTypeEnum.SWITCH;
-        } else if(nodeComponent instanceof NodeIfComponent){
-            type = NodeTypeEnum.IF;
-        }else if(nodeComponent instanceof NodeComponent) {
-            type = NodeTypeEnum.COMMON;
-        }
+        //根据class来猜测类型
+        NodeTypeEnum type = NodeTypeEnum.guessTypeByClazz(nodeComponent.getClass());
 
         if (type == null){
             throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId));
@@ -144,6 +138,48 @@ public class FlowBus {
         addNode(nodeId, name, NodeTypeEnum.IF, cmpClazz, null);
     }
 
+    public static void addForNode(String nodeId, String name, String cmpClazzStr){
+        Class<?> cmpClazz;
+        try{
+            cmpClazz = Class.forName(cmpClazzStr);
+        }catch (Exception e){
+            throw new ComponentCannotRegisterException(e.getMessage());
+        }
+        addNode(nodeId, name, NodeTypeEnum.FOR, cmpClazz, null);
+    }
+
+    public static void addForNode(String nodeId, String name, Class<?> cmpClazz){
+        addNode(nodeId, name, NodeTypeEnum.FOR, cmpClazz, null);
+    }
+
+    public static void addWhileNode(String nodeId, String name, String cmpClazzStr){
+        Class<?> cmpClazz;
+        try{
+            cmpClazz = Class.forName(cmpClazzStr);
+        }catch (Exception e){
+            throw new ComponentCannotRegisterException(e.getMessage());
+        }
+        addNode(nodeId, name, NodeTypeEnum.WHILE, cmpClazz, null);
+    }
+
+    public static void addWhileNode(String nodeId, String name, Class<?> cmpClazz){
+        addNode(nodeId, name, NodeTypeEnum.WHILE, cmpClazz, null);
+    }
+
+    public static void addBreakNode(String nodeId, String name, String cmpClazzStr){
+        Class<?> cmpClazz;
+        try{
+            cmpClazz = Class.forName(cmpClazzStr);
+        }catch (Exception e){
+            throw new ComponentCannotRegisterException(e.getMessage());
+        }
+        addNode(nodeId, name, NodeTypeEnum.BREAK, cmpClazz, null);
+    }
+
+    public static void addBreakNode(String nodeId, String name, Class<?> cmpClazz){
+        addNode(nodeId, name, NodeTypeEnum.BREAK, cmpClazz, null);
+    }
+
     public static void addCommonScriptNode(String nodeId, String name, String script){
         addNode(nodeId, name, NodeTypeEnum.SCRIPT, ScriptComponent.class, script);
     }
@@ -156,6 +192,18 @@ public class FlowBus {
         addNode(nodeId, name, NodeTypeEnum.IF_SCRIPT, ScriptIfComponent.class, script);
     }
 
+    public static void addForScriptNode(String nodeId, String name, String script){
+        addNode(nodeId, name, NodeTypeEnum.FOR_SCRIPT, ScriptIfComponent.class, script);
+    }
+
+    public static void addWhileScriptNode(String nodeId, String name, String script){
+        addNode(nodeId, name, NodeTypeEnum.WHILE_SCRIPT, ScriptIfComponent.class, script);
+    }
+
+    public static void addBreakScriptNode(String nodeId, String name, String script){
+        addNode(nodeId, name, NodeTypeEnum.BREAK_SCRIPT, ScriptIfComponent.class, script);
+    }
+
     private static void addNode(String nodeId, String name, NodeTypeEnum type, Class<?> cmpClazz, String script) {
         try {
             //判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例
@@ -179,7 +227,7 @@ public class FlowBus {
                 //以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置
                 //这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了
                 //如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance
-                if (!CollectionUtil.newArrayList(NodeTypeEnum.SCRIPT, NodeTypeEnum.SWITCH_SCRIPT, NodeTypeEnum.IF_SCRIPT).contains(type)){
+                if (!type.isScript()){
                     cmpInstances = ListUtil.toList((NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz));
                 }
                 // 去除null元素

+ 75 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ForCondition.java

@@ -0,0 +1,75 @@
+package com.yomahub.liteflow.flow.element.condition;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.exception.NoForNodeException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.Slot;
+import com.yomahub.liteflow.util.LiteFlowProxyUtil;
+
+/**
+ * 循环次数Condition
+ *
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class ForCondition extends LoopCondition{
+
+    private Node forNode;
+
+    @Override
+    public void execute(Integer slotIndex) throws Exception {
+        Slot slot = DataBus.getSlot(slotIndex);
+        if (ObjectUtil.isNull(forNode)){
+            String errorInfo = StrUtil.format("[{}]:no for-node found", slot.getRequestId());
+            throw new NoForNodeException(errorInfo);
+        }
+
+        //执行forCount组件
+        forNode.setCurrChainName(this.getCurrChainName());
+        forNode.execute(slotIndex);
+
+        //这里可能会有spring代理过的bean,所以拿到user原始的class
+        Class<?> originalForCountClass = LiteFlowProxyUtil.getUserClass(this.forNode.getClass());
+        //获得循环次数
+        int forCount = slot.getForResult(originalForCountClass.getName());
+
+        //获得要循环的可执行对象
+        Executable executableItem = this.getDoExecutor();
+
+        //循环执行
+        for (int i = 0; i < forCount; i++) {
+            executableItem.execute(slotIndex);
+            //如果break组件不为空,则去执行
+            if (ObjectUtil.isNotNull(breakNode)){
+                breakNode.setCurrChainName(this.getCurrChainName());
+                Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(this.breakNode.getClass());
+                boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
+                if (isBreak){
+                    break;
+                }
+            }
+        }
+
+    }
+
+    @Override
+    public ConditionTypeEnum getConditionType() {
+        return ConditionTypeEnum.TYPE_FOR;
+    }
+
+    public Executable getDoExecutor() {
+        return this.getExecutableList().get(0);
+    }
+
+    public Node getForNode() {
+        return forNode;
+    }
+
+    public void setForNode(Node forNode) {
+        this.forNode = forNode;
+    }
+}

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/IfCondition.java

@@ -74,7 +74,7 @@ public class IfCondition extends Condition {
 
     @Override
     public ConditionTypeEnum getConditionType() {
-        return null;
+        return ConditionTypeEnum.TYPE_IF;
     }
 
     public Executable getTrueCaseExecutableItem() {

+ 23 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/LoopCondition.java

@@ -0,0 +1,23 @@
+package com.yomahub.liteflow.flow.element.condition;
+
+import com.yomahub.liteflow.flow.element.Node;
+
+/**
+ * 循环Condition的抽象类
+ * 主要继承对象有ForCondition和WhileCondition
+ *
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public abstract class LoopCondition extends Condition {
+
+    protected Node breakNode;
+
+    public Node getBreakNode() {
+        return breakNode;
+    }
+
+    public void setBreakNode(Node breakNode) {
+        this.breakNode = breakNode;
+    }
+}

+ 74 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhileCondition.java

@@ -0,0 +1,74 @@
+package com.yomahub.liteflow.flow.element.condition;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.exception.NoWhileNodeException;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.Slot;
+import com.yomahub.liteflow.util.LiteFlowProxyUtil;
+
+/**
+ * 循环条件Condition
+ *
+ * @author Bryan.Zhang
+ * @since 2.9.0
+ */
+public class WhileCondition extends LoopCondition{
+
+    private Node whileNode;
+
+    @Override
+    public void execute(Integer slotIndex) throws Exception {
+        Slot slot = DataBus.getSlot(slotIndex);
+        if (ObjectUtil.isNull(whileNode)){
+            String errorInfo = StrUtil.format("[{}]:no while-node found", slot.getRequestId());
+            throw new NoWhileNodeException(errorInfo);
+        }
+
+        //获得要循环的可执行对象
+        Executable executableItem = this.getDoExecutor();
+
+        //循环执行
+        while(getWhileResult(slotIndex)){
+            executableItem.execute(slotIndex);
+            //如果break组件不为空,则去执行
+            if (ObjectUtil.isNotNull(breakNode)){
+                breakNode.setCurrChainName(this.getCurrChainName());
+                Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(this.breakNode.getClass());
+                boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
+                if (isBreak){
+                    break;
+                }
+            }
+        }
+    }
+
+    private boolean getWhileResult(Integer slotIndex) throws Exception{
+        Slot slot = DataBus.getSlot(slotIndex);
+        //执行while组件
+        whileNode.setCurrChainName(this.getCurrChainName());
+        whileNode.execute(slotIndex);
+        Class<?> originalWhileClass = LiteFlowProxyUtil.getUserClass(this.whileNode.getClass());
+        return slot.getWhileResult(originalWhileClass.getName());
+    }
+
+    public Executable getDoExecutor() {
+        return this.getExecutableList().get(0);
+    }
+
+    @Override
+    public ConditionTypeEnum getConditionType() {
+        return ConditionTypeEnum.TYPE_WHILE;
+    }
+
+    public Node getWhileNode() {
+        return whileNode;
+    }
+
+    public void setWhileNode(Node whileNode) {
+        this.whileNode = whileNode;
+    }
+}

+ 28 - 11
liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java

@@ -6,9 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.fasterxml.jackson.databind.JsonNode;
-import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
-import com.yomahub.liteflow.annotation.LiteflowIfCmpDefine;
-import com.yomahub.liteflow.annotation.LiteflowSwitchCmpDefine;
+import com.yomahub.liteflow.annotation.*;
 import com.yomahub.liteflow.builder.LiteFlowChainBuilder;
 import com.yomahub.liteflow.builder.LiteFlowConditionBuilder;
 import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
@@ -61,18 +59,16 @@ public class ParserHelper {
 		String type = nodePropBean.getType();
 		String file = nodePropBean.getFile();
 
-		//先尝试自动推断类型
+		//clazz有值的,基本都不是脚本节点
+		//脚本节点,都必须配置type
+		//非脚本节点的先尝试自动推断类型
 		if (StrUtil.isNotBlank(clazz)) {
 			try {
 				//先尝试从继承的类型中推断
 				Class<?> c = Class.forName(clazz);
-				Object o = ReflectUtil.newInstanceIfPossible(c);
-				if (o instanceof NodeSwitchComponent) {
-					type = NodeTypeEnum.SWITCH.getCode();
-				}else if(o instanceof NodeIfComponent){
-					type = NodeTypeEnum.IF.getCode();
-				}else if (o instanceof NodeComponent) {
-					type = NodeTypeEnum.COMMON.getCode();
+				NodeTypeEnum nodeType = NodeTypeEnum.guessTypeByClazz(c);
+				if (nodeType != null){
+					type = nodeType.getCode();
 				}
 
 				//再尝试声明式组件这部分的推断
@@ -96,6 +92,27 @@ public class ParserHelper {
 						type = NodeTypeEnum.IF.getCode();
 					}
 				}
+
+				if (type == null) {
+					LiteflowForCmpDefine liteflowForCmpDefine = AnnotationUtil.getAnnotation(c, LiteflowForCmpDefine.class);
+					if (liteflowForCmpDefine != null) {
+						type = NodeTypeEnum.FOR.getCode();
+					}
+				}
+
+				if (type == null) {
+					LiteflowWhileCmpDefine liteflowWhileCmpDefine = AnnotationUtil.getAnnotation(c, LiteflowWhileCmpDefine.class);
+					if (liteflowWhileCmpDefine != null) {
+						type = NodeTypeEnum.WHILE.getCode();
+					}
+				}
+
+				if (type == null) {
+					LiteflowBreakCmpDefine liteflowBreakCmpDefine = AnnotationUtil.getAnnotation(c, LiteflowBreakCmpDefine.class);
+					if (liteflowBreakCmpDefine != null) {
+						type = NodeTypeEnum.BREAK.getCode();
+					}
+				}
 			} catch (Exception e) {
 				throw new NodeClassNotFoundException(StrUtil.format("cannot find the node[{}]", clazz));
 			}

+ 30 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java

@@ -46,6 +46,12 @@ public class Slot{
 
 	private static final String IF_NODE_PREFIX = "_if_";
 
+	private static final String FOR_PREFIX = "_for_";
+
+	private static final String WHILE_PREFIX = "_while_";
+
+	private static final String BREAK_PREFIX = "_break_";
+
 	private static final String NODE_INPUT_PREFIX = "_input_";
 
 	private static final String NODE_OUTPUT_PREFIX = "_output_";
@@ -204,6 +210,30 @@ public class Slot{
 		return (boolean) metaDataMap.get(IF_NODE_PREFIX + key);
 	}
 
+	public void setForResult(String key, int forCount){
+		putMetaDataMap(FOR_PREFIX + key, forCount);
+	}
+
+	public int getForResult(String key){
+		return (int) metaDataMap.get(FOR_PREFIX + key);
+	}
+
+	public void setWhileResult(String key, boolean whileFlag){
+		putMetaDataMap(WHILE_PREFIX + key, whileFlag);
+	}
+
+	public boolean getWhileResult(String key){
+		return (boolean) metaDataMap.get(WHILE_PREFIX + key);
+	}
+
+	public void setBreakResult(String key, boolean breakFlag){
+		putMetaDataMap(BREAK_PREFIX + key, breakFlag);
+	}
+
+	public boolean getBreakResult(String key){
+		return (boolean) metaDataMap.get(BREAK_PREFIX + key);
+	}
+
 	public void setChainName(String chainName) {
 		if (!hasMetaData(CHAIN_NAME)){
 			this.putMetaDataMap(CHAIN_NAME, chainName);

+ 2 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/util/LOGOPrinter.java

@@ -3,6 +3,8 @@ package com.yomahub.liteflow.util;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Optional;
+
 /**
  * logo打印器
  * @author Bryan.Zhang

+ 21 - 8
liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteFlowProxyUtil.java

@@ -2,13 +2,8 @@ package com.yomahub.liteflow.util;
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
-import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
-import com.yomahub.liteflow.annotation.LiteflowIfCmpDefine;
-import com.yomahub.liteflow.annotation.LiteflowMethod;
-import com.yomahub.liteflow.annotation.LiteflowSwitchCmpDefine;
-import com.yomahub.liteflow.core.NodeComponent;
-import com.yomahub.liteflow.core.NodeIfComponent;
-import com.yomahub.liteflow.core.NodeSwitchComponent;
+import com.yomahub.liteflow.annotation.*;
+import com.yomahub.liteflow.core.*;
 import com.yomahub.liteflow.core.proxy.ComponentProxy;
 import com.yomahub.liteflow.exception.ComponentProxyErrorException;
 import com.yomahub.liteflow.exception.LiteFlowException;
@@ -50,6 +45,9 @@ public class LiteFlowProxyUtil {
             LiteflowCmpDefine liteflowCmpDefine = bean.getClass().getAnnotation(LiteflowCmpDefine.class);
             LiteflowSwitchCmpDefine liteflowSwitchCmpDefine = bean.getClass().getAnnotation(LiteflowSwitchCmpDefine.class);
             LiteflowIfCmpDefine liteflowIfCmpDefine = bean.getClass().getAnnotation(LiteflowIfCmpDefine.class);
+            LiteflowForCmpDefine liteflowForCmpDefine = bean.getClass().getAnnotation(LiteflowForCmpDefine.class);
+            LiteflowWhileCmpDefine liteflowWhileCmpDefine = bean.getClass().getAnnotation(LiteflowWhileCmpDefine.class);
+            LiteflowBreakCmpDefine liteflowBreakCmpDefine = bean.getClass().getAnnotation(LiteflowBreakCmpDefine.class);
 
             ComponentProxy proxy;
             if (ObjectUtil.isNotNull(liteflowCmpDefine)){
@@ -66,7 +64,22 @@ public class LiteFlowProxyUtil {
                 proxy = new ComponentProxy(nodeId, bean, NodeIfComponent.class);
                 return proxy.getProxyList();
             }
-            return new ComponentProxy(nodeId, bean, NodeIfComponent.class).getProxyList();
+
+            if (ObjectUtil.isNotNull(liteflowForCmpDefine)){
+                proxy = new ComponentProxy(nodeId, bean, NodeForComponent.class);
+                return proxy.getProxyList();
+            }
+
+            if (ObjectUtil.isNotNull(liteflowWhileCmpDefine)){
+                proxy = new ComponentProxy(nodeId, bean, NodeWhileComponent.class);
+                return proxy.getProxyList();
+            }
+
+            if (ObjectUtil.isNotNull(liteflowBreakCmpDefine)){
+                proxy = new ComponentProxy(nodeId, bean, NodeBreakComponent.class);
+                return proxy.getProxyList();
+            }
+            return new ComponentProxy(nodeId, bean, NodeComponent.class).getProxyList();
         }catch (LiteFlowException liteFlowException){
             throw liteFlowException;
         }

+ 1 - 1
liteflow-script-plugin/liteflow-script-groovy/src/main/java/com/yomahub/liteflow/script/groovy/GroovyScriptExecutor.java

@@ -71,7 +71,7 @@ public class GroovyScriptExecutor implements ScriptExecutor {
             Slot slot = DataBus.getSlot(slotIndex);
             bindings.put("requestData", slot.getRequestData());
 
-            //如果有隐流程,则放入隐式流程的流程参数
+            //如果有隐流程,则放入隐式流程的流程参数
             Object subRequestData = slot.getChainReqData(currChainName);
             if (ObjectUtil.isNotNull(subRequestData)){
                 bindings.put("subRequestData", subRequestData);