feature #I3N2E2 支持编程时式的注册组件的方式
This commit is contained in:
parent
d2c7779532
commit
25438c17fe
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
package com.yomahub.liteflow.exception;
|
||||
|
||||
/**
|
||||
* 流程规则主要执行器类
|
||||
* @author Bryan.Zhang
|
||||
* @since 2.5.3
|
||||
*/
|
||||
public class ComponentCannotRegisterException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 异常信息 */
|
||||
private String message;
|
||||
|
||||
public ComponentCannotRegisterException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
|
@ -12,9 +12,15 @@ import java.util.Map;
|
|||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.flow.Chain;
|
||||
import com.yomahub.liteflow.entity.flow.Node;
|
||||
import com.yomahub.liteflow.exception.ComponentCannotRegisterException;
|
||||
import com.yomahub.liteflow.util.SpringAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 流程元数据类
|
||||
|
|
@ -22,9 +28,11 @@ import com.yomahub.liteflow.util.SpringAware;
|
|||
*/
|
||||
public class FlowBus {
|
||||
|
||||
private static Map<String, Chain> chainMap = new HashMap<>();
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FlowBus.class);
|
||||
|
||||
private static Map<String, Node> nodeMap = new HashMap<>();
|
||||
private static final Map<String, Chain> chainMap = new HashMap<>();
|
||||
|
||||
private static final Map<String, Node> nodeMap = new HashMap<>();
|
||||
|
||||
private FlowBus() {
|
||||
}
|
||||
|
|
@ -56,6 +64,34 @@ public class FlowBus {
|
|||
nodeMap.put(nodeId, node);
|
||||
}
|
||||
|
||||
public static void addNode(String nodeId, String cmpClazzStr) throws Exception{
|
||||
Class<NodeComponent> cmpClazz = (Class<NodeComponent>)Class.forName(cmpClazzStr);
|
||||
addNode(nodeId, cmpClazz);
|
||||
}
|
||||
|
||||
public static void addNode(String nodeId, Class<? extends NodeComponent> cmpClazz){
|
||||
try{
|
||||
Node node = new Node();
|
||||
node.setId(nodeId);
|
||||
node.setClazz(cmpClazz.getName());
|
||||
//以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置
|
||||
//这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了
|
||||
NodeComponent cmpInstance = SpringAware.registerOrGet(cmpClazz);
|
||||
if (ObjectUtil.isNull(cmpInstance)) {
|
||||
LOG.warn("couldn't find component class [{}] from spring context", cmpClazz.getName());
|
||||
cmpInstance = cmpClazz.newInstance();
|
||||
}
|
||||
cmpInstance.setNodeId(nodeId);
|
||||
cmpInstance.setSelf(cmpInstance);
|
||||
node.setInstance(cmpInstance);
|
||||
nodeMap.put(nodeId,node);
|
||||
}catch (Exception e){
|
||||
String error = StrUtil.format("component[{}] register error", cmpClazz.getName());
|
||||
LOG.error(error, e);
|
||||
throw new ComponentCannotRegisterException(error);
|
||||
}
|
||||
}
|
||||
|
||||
public static Node getNode(String nodeId) {
|
||||
return nodeMap.get(nodeId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,28 +47,10 @@ public abstract class XmlFlowParser extends FlowParser{
|
|||
List<Element> nodeList = rootElement.element("nodes").elements("node");
|
||||
String id;
|
||||
String clazz;
|
||||
Node node;
|
||||
NodeComponent component;
|
||||
Class<NodeComponent> nodeComponentClass;
|
||||
for (Element e : nodeList) {
|
||||
node = new Node();
|
||||
id = e.attributeValue("id");
|
||||
clazz = e.attributeValue("class");
|
||||
node.setId(id);
|
||||
node.setClazz(clazz);
|
||||
nodeComponentClass = (Class<NodeComponent>)Class.forName(clazz);
|
||||
|
||||
//以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置
|
||||
//这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了
|
||||
component = SpringAware.registerOrGet(nodeComponentClass);
|
||||
if (ObjectUtil.isNull(component)) {
|
||||
LOG.error("couldn't find component class [{}] from spring context", clazz);
|
||||
component = nodeComponentClass.newInstance();
|
||||
}
|
||||
component.setNodeId(id);
|
||||
component.setSelf(component);
|
||||
node.setInstance(component);
|
||||
FlowBus.addNode(id, node);
|
||||
FlowBus.addNode(id, clazz);
|
||||
}
|
||||
} else {
|
||||
for (Entry<String, NodeComponent> componentEntry : ComponentScanner.nodeComponentMap.entrySet()) {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ public class LiteflowConfig {
|
|||
//异步线程池最大队列数量
|
||||
private Integer whenQueueLimit;
|
||||
|
||||
//是否在启动时解析规则文件
|
||||
//这个参数主要给编码式注册元数据的场景用的,结合FlowBus.addNode一起用
|
||||
private Boolean parseOnStart;
|
||||
|
||||
public String getRuleSource() {
|
||||
return ruleSource;
|
||||
}
|
||||
|
|
@ -148,4 +152,16 @@ public class LiteflowConfig {
|
|||
public void setWhenQueueLimit(Integer whenQueueLimit) {
|
||||
this.whenQueueLimit = whenQueueLimit;
|
||||
}
|
||||
|
||||
public Boolean isParseOnStart() {
|
||||
if (ObjectUtil.isNull(parseOnStart)){
|
||||
return true;
|
||||
}else{
|
||||
return parseOnStart;
|
||||
}
|
||||
}
|
||||
|
||||
public void setParseOnStart(Boolean parseOnStart) {
|
||||
this.parseOnStart = parseOnStart;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.yomahub.liteflow.springboot;
|
|||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
||||
/**
|
||||
* 执行器初始化类
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.yomahub.liteflow.property.LiteflowConfig;
|
|||
import com.yomahub.liteflow.util.SpringAware;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
|
@ -35,6 +36,7 @@ public class LiteflowMainAutoConfiguration {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "liteflow",name = "parse-on-start",havingValue = "true")
|
||||
public LiteflowExecutorInit liteflowExecutorInit(FlowExecutor flowExecutor) {
|
||||
return new LiteflowExecutorInit(flowExecutor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ public class LiteflowProperty {
|
|||
//异步线程池最大队列数量
|
||||
private int whenQueueLimit;
|
||||
|
||||
//是否在启动时解析规则文件
|
||||
//这个参数主要给编码式注册元数据的场景用的,结合FlowBus.addNode一起用
|
||||
private boolean parseOnStart;
|
||||
|
||||
public String getRuleSource() {
|
||||
return ruleSource;
|
||||
}
|
||||
|
|
@ -63,4 +67,12 @@ public class LiteflowProperty {
|
|||
public void setWhenQueueLimit(int whenQueueLimit) {
|
||||
this.whenQueueLimit = whenQueueLimit;
|
||||
}
|
||||
|
||||
public boolean isParseOnStart() {
|
||||
return parseOnStart;
|
||||
}
|
||||
|
||||
public void setParseOnStart(boolean parseOnStart) {
|
||||
this.parseOnStart = parseOnStart;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public class LiteflowPropertyAutoConfiguration {
|
|||
liteflowConfig.setPeriod(liteflowMonitorProperty.getPeriod());
|
||||
liteflowConfig.setWhenMaxWorkers(property.getWhenMaxWorkers());
|
||||
liteflowConfig.setWhenQueueLimit(property.getWhenQueueLimit());
|
||||
liteflowConfig.setParseOnStart(property.isParseOnStart());
|
||||
return liteflowConfig;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@
|
|||
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
|
||||
"defaultValue": 512
|
||||
},
|
||||
{
|
||||
"name": "liteflow.parse-on-start",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Set whether the rule file needs to be parsed at startup.",
|
||||
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "liteflow.monitor.enable-log",
|
||||
"type": "java.lang.Boolean",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ liteflow.slot-size=1024
|
|||
liteflow.when-max-wait-seconds=15
|
||||
liteflow.when-max-workers=4
|
||||
liteflow.when-queue-limit=512
|
||||
liteflow.parse-on-start=true
|
||||
liteflow.monitor.enable-log=false
|
||||
liteflow.monitor.queue-limit=200
|
||||
liteflow.monitor.delay=300000
|
||||
|
|
|
|||
|
|
@ -48,5 +48,6 @@ public class LiteflowConfigSpringbootTest extends BaseTest {
|
|||
Assert.assertFalse(config.getEnableLog());
|
||||
Assert.assertEquals(4, config.getWhenMaxWorkers().longValue());
|
||||
Assert.assertEquals(512, config.getWhenQueueLimit().longValue());
|
||||
Assert.assertEquals(true, config.isParseOnStart());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package com.yomahub.liteflow.test.flowmeta;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.entity.data.DefaultSlot;
|
||||
import com.yomahub.liteflow.entity.data.LiteflowResponse;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import com.yomahub.liteflow.test.flowmeta.cmp2.DCmp;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
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.junit4.SpringRunner;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@TestPropertySource(value = "classpath:/flowmeta/application.properties")
|
||||
@SpringBootTest(classes = FlowMetaSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.flowmeta.cmp1"})
|
||||
public class FlowMetaSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
//测试自定义AOP,串行场景
|
||||
@Test
|
||||
public void testFlowMeta() {
|
||||
FlowBus.addNode("d", DCmp.class);
|
||||
LiteflowResponse<DefaultSlot> response= flowExecutor.execute2Resp("chain1", "it's a request");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("a==>b==>c==>d", response.getSlot().printStep());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.flowmeta.cmp1;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.flowmeta.cmp1;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.flowmeta.cmp1;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.flowmeta.cmp2;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("d")
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("Dcomp executed!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
liteflow.rule-source=flowmeta/flow.xml
|
||||
liteflow.parse-on-start=false
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
<then value="a,b,c,d"/>
|
||||
</chain>
|
||||
</flow>
|
||||
|
|
@ -5,5 +5,4 @@ liteflow.rule-source=config/flow.json;com.yomahub.flowtest.custom.CustomXmlClass
|
|||
liteflow.when-max-wait-seconds=20
|
||||
liteflow.monitor.enable-log=true
|
||||
liteflow.monitor.queue-limit=300
|
||||
liteflow.monitor.delay=10000
|
||||
#liteflow.monitor.period=10000
|
||||
liteflow.monitor.delay=10000
|
||||
Loading…
Reference in New Issue