feature #I4UPWG 模块架构调整,支持非Spring的项目使用

This commit is contained in:
bryan31 2022-02-22 14:13:26 +08:00
parent cf6a527f97
commit 714914687f
97 changed files with 1013 additions and 261 deletions

View File

@ -23,26 +23,6 @@
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>

View File

@ -0,0 +1,11 @@
package com.yomahub.liteflow.annotation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {
String value() default "";
}

View File

@ -1,7 +1,5 @@
package com.yomahub.liteflow.annotation;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**

View File

@ -0,0 +1,50 @@
package com.yomahub.liteflow.annotation.util;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.yomahub.liteflow.annotation.AliasFor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class AnnoUtil {
public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
A annotation = AnnotationUtil.getAnnotation(annotatedElement, annotationType);
if (ObjectUtil.isNull(annotation)){
return null;
}
Map<String, String> aliasMap = new HashMap<>();
Map<String, Object> defaultValueMap = new HashMap<>();
Arrays.stream(ReflectUtil.getMethods(annotationType)).forEach(method -> {
AliasFor aliasFor = AnnotationUtil.getAnnotation(method, AliasFor.class);
if (ObjectUtil.isNotNull(aliasFor)){
aliasMap.put(method.getName(), aliasFor.value());
defaultValueMap.put(method.getName(), getDefaultValue(annotationType, method.getName()));
}
});
aliasMap.forEach((key, value1) -> {
Object value = ReflectUtil.invoke(annotation, key);
Object defaultValue = defaultValueMap.get(key);
if (ObjectUtil.notEqual(value, defaultValue)) {
AnnotationUtil.setValue(annotation, value1, value);
}
});
return annotation;
}
public static <A extends Annotation> Object getDefaultValue(Class<A> annotationType, String property){
try{
return annotationType.getMethod(property).getDefaultValue();
}catch (Exception e){
return null;
}
}
}

View File

@ -11,7 +11,7 @@ import com.yomahub.liteflow.exception.ExecutableItemNotFoundException;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.parser.RegexEntity;
import com.yomahub.liteflow.parser.RegexNodeEntity;
import com.yomahub.liteflow.util.SpringAware;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import java.util.ArrayList;
@ -88,7 +88,7 @@ public class LiteFlowConditionBuilder {
this.condition.getNodeList().add(chain);
} else {
//元数据没有的话从spring上下文再取一遍这部分是为了防止标有@Lazy懒加载的组件
NodeComponent nodeComponent = SpringAware.getBean(item.getId());
NodeComponent nodeComponent = ContextAwareFactory.loadContextAware().getBean(item.getId());
if (ObjectUtil.isNotNull(nodeComponent)){
FlowBus.addSpringScanNode(item.getId(), nodeComponent);
return setValue(value);

View File

@ -2,13 +2,13 @@ package com.yomahub.liteflow.core;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowRetry;
import com.yomahub.liteflow.annotation.util.AnnoUtil;
import com.yomahub.liteflow.entity.executor.NodeExecutor;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import org.springframework.core.annotation.AnnotationUtils;
import com.yomahub.liteflow.spi.factory.LiteflowComponentSupportFactory;
/**
* 组件初始化器
@ -31,23 +31,17 @@ public class ComponentInitializer {
nodeComponent.setSelf(nodeComponent);
nodeComponent.setType(type);
//先取传进来的name值(配置文件中配置的)再看有没有配置LiteflowComponent标注
//先取传进来的name值(配置文件中配置的)再看有没有配置@LiteflowComponent标注
//@LiteflowComponent标注只在spring体系下生效这里用了spi机制取到相应环境下的实现类
nodeComponent.setName(desc);
if (nodeComponent.getType().equals(NodeTypeEnum.COMMON) && StrUtil.isBlank(nodeComponent.getName())){
//判断NodeComponent是否是标识了@LiteflowComponent的标注
//如果标注了那么要从中取到name字段
LiteflowComponent liteflowComponent = nodeComponent.getClass().getAnnotation(LiteflowComponent.class);
if (ObjectUtil.isNotNull(liteflowComponent)) {
String name = liteflowComponent.name();
if (StrUtil.isNotBlank(name)) {
nodeComponent.setName(name);
}
}
String name = LiteflowComponentSupportFactory.loadLiteflowComponentSupport().getCmpName(nodeComponent);
nodeComponent.setName(name);
}
//先从组件上取@RetryCount标注如果没有则看全局配置全局配置如果不配置的话默认是0
//默认retryForExceptions为Exception.class
LiteflowRetry liteflowRetryAnnotation = AnnotationUtils.getAnnotation(nodeComponent.getClass(), LiteflowRetry.class);
LiteflowRetry liteflowRetryAnnotation = AnnoUtil.getAnnotation(nodeComponent.getClass(), LiteflowRetry.class);
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
if (ObjectUtil.isNotNull(liteflowRetryAnnotation)) {
nodeComponent.setRetryCount(liteflowRetryAnnotation.retry());

View File

@ -18,7 +18,7 @@ import com.yomahub.liteflow.enums.FlowParserTypeEnum;
import com.yomahub.liteflow.exception.*;
import com.yomahub.liteflow.parser.*;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.util.SpringAware;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -175,11 +175,11 @@ public class FlowExecutor {
Class<?> c = Class.forName(path);
switch (pattern) {
case TYPE_XML:
return (XmlFlowParser) SpringAware.registerBean(c);
return (XmlFlowParser) ContextAwareFactory.loadContextAware().registerBean(c);
case TYPE_JSON:
return (JsonFlowParser) SpringAware.registerBean(c);
return (JsonFlowParser) ContextAwareFactory.loadContextAware().registerBean(c);
case TYPE_YML:
return (YmlFlowParser) SpringAware.registerBean(c);
return (YmlFlowParser) ContextAwareFactory.loadContextAware().registerBean(c);
default:
}
} else if (isZKConfig(path)) {

View File

@ -14,9 +14,10 @@ import com.alibaba.ttl.TransmittableThreadLocal;
import com.yomahub.liteflow.entity.executor.NodeExecutor;
import com.yomahub.liteflow.entity.executor.DefaultNodeExecutor;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.spi.factory.CmpAroundAspectFactory;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.yomahub.liteflow.entity.data.CmpStep;
import com.yomahub.liteflow.entity.data.CmpStepType;
@ -25,7 +26,6 @@ import com.yomahub.liteflow.entity.data.Slot;
import com.yomahub.liteflow.entity.flow.Executable;
import com.yomahub.liteflow.entity.monitor.CompStatistics;
import com.yomahub.liteflow.monitor.MonitorBus;
import com.yomahub.liteflow.spring.ComponentScanner;
import java.util.Map;
@ -39,7 +39,6 @@ public abstract class NodeComponent{
private final TransmittableThreadLocal<Integer> slotIndexTL = new TransmittableThreadLocal<>();
@Autowired(required = false)
private MonitorBus monitorBus;
private final TransmittableThreadLocal<String> tagTL = new TransmittableThreadLocal<>();
@ -69,16 +68,23 @@ public abstract class NodeComponent{
//是否结束整个流程这个只对串行流程有效并行流程无效
private final TransmittableThreadLocal<Boolean> isEndTL = new TransmittableThreadLocal<>();
public NodeComponent() {
monitorBus = ContextAwareFactory.loadContextAware().getBean(MonitorBus.class);
}
public void execute() throws Exception{
Slot slot = this.getSlot();
LOG.info("[{}]:[O]start component[{}] execution",slot.getRequestId(),this.getClass().getSimpleName());
slot.addStep(new CmpStep(nodeId, name, CmpStepType.SINGLE));
StopWatch stopWatch = new StopWatch();
stopWatch.start();
self.beforeProcess(this.getNodeId(), slot);
//全局切面只在spring体系下生效这里用了spi机制取到相应环境下的实现类
//非spring环境下全局切面为空实现
CmpAroundAspectFactory.loadCmpAroundAspect().beforeProcess(this.getNodeId(), slot);
self.process();
self.afterProcess(this.getNodeId(), slot);
CmpAroundAspectFactory.loadCmpAroundAspect().afterProcess(this.getNodeId(), slot);
stopWatch.stop();
@ -104,21 +110,6 @@ public abstract class NodeComponent{
public abstract void process() throws Exception;
//process前置处理
public void beforeProcess(String nodeId, Slot slot) {
if (ObjectUtil.isNotNull(ComponentScanner.cmpAroundAspect)) {
ComponentScanner.cmpAroundAspect.beforeProcess(nodeId, slot);
}
}
//process后置处理
public void afterProcess(String nodeId, Slot slot) {
if (ObjectUtil.isNotNull(ComponentScanner.cmpAroundAspect)) {
ComponentScanner.cmpAroundAspect.afterProcess(nodeId, slot);
}
}
//是否进入该节点
public boolean isAccess(){
return true;

View File

@ -1,10 +1,8 @@
package com.yomahub.liteflow.entity.executor;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.google.common.collect.Maps;
import com.yomahub.liteflow.util.SpringAware;
import org.apache.commons.lang.StringUtils;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import java.util.Map;
@ -43,7 +41,7 @@ public class NodeExecutorHelper {
// 此处无需使用同步锁进行同步-因为即使同时创建了两个实例但是添加到缓存中的只会存在一个且不会存在并发问题-具体是由ConcurrentMap保证
if (ObjectUtil.isNull(nodeExecutor)) {
// 获取重试执行器实例
nodeExecutor = SpringAware.registerBean(nodeExecutorClass);
nodeExecutor = ContextAwareFactory.loadContextAware().registerBean(nodeExecutorClass);
// 缓存
nodeExecutorMap.put(nodeExecutorClass, nodeExecutor);
}

View File

@ -18,29 +18,21 @@ import com.yomahub.liteflow.core.ScriptComponent;
import com.yomahub.liteflow.core.ScriptCondComponent;
import com.yomahub.liteflow.entity.data.DataBus;
import com.yomahub.liteflow.entity.flow.Chain;
import com.yomahub.liteflow.entity.flow.Condition;
import com.yomahub.liteflow.entity.flow.Node;
import com.yomahub.liteflow.enums.FlowParserTypeEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.ComponentCannotRegisterException;
import com.yomahub.liteflow.exception.NodeTypeNotSupportException;
import com.yomahub.liteflow.parser.LocalJsonFlowParser;
import com.yomahub.liteflow.parser.LocalXmlFlowParser;
import com.yomahub.liteflow.parser.LocalYmlFlowParser;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.script.ScriptExecutor;
import com.yomahub.liteflow.script.ScriptExecutorFactory;
import com.yomahub.liteflow.script.exception.ScriptSpiException;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.util.CopyOnWriteHashMap;
import com.yomahub.liteflow.util.SpringAware;
import org.checkerframework.checker.units.qual.C;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SerializationUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -114,7 +106,7 @@ public class FlowBus {
//如果是script类型的节点因为class只有一个所以也不能注册进spring上下文注册的时候需要new Instance
NodeComponent cmpInstance = null;
if (!CollectionUtil.newArrayList(NodeTypeEnum.SCRIPT, NodeTypeEnum.COND_SCRIPT).contains(type)){
cmpInstance = SpringAware.registerOrGet(nodeId, cmpClazz);
cmpInstance = ContextAwareFactory.loadContextAware().registerOrGet(nodeId, cmpClazz);
}
if (ObjectUtil.isNull(cmpInstance)) {

View File

@ -1,19 +1,5 @@
package com.yomahub.liteflow.parser;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import com.google.common.collect.Lists;
import com.yomahub.liteflow.entity.flow.*;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.exception.ConfigErrorException;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import java.io.IOException;
import java.util.*;
/**
@ -21,46 +7,10 @@ import java.util.*;
* @author guodongqing
* @since 2.5.0
*/
public abstract class FlowParser {
public interface FlowParser {
public abstract void parseMain(List<String> pathList) throws Exception;
void parseMain(List<String> pathList) throws Exception;
public abstract void parse(List<String> contentList) throws Exception;
void parse(List<String> contentList) throws Exception;
//根据配置的ruleSource查找匹配的资源
protected Resource[] matchRuleResources(final List<String> pathList) throws IOException {
Assert.notEmpty(pathList, "rule source must not be null");
List<Resource> allResource = new ArrayList<>();
for (String path : pathList) {
String locationPattern;
//如果path是绝对路径且这个文件存在时我们认为这是一个本地文件路径而并非classpath路径
if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)){
locationPattern = ResourceUtils.FILE_URL_PREFIX + path;
} else {
if (!path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
locationPattern = ResourceUtils.CLASSPATH_URL_PREFIX + path;
}else{
locationPattern = path;
}
}
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources(locationPattern);
if (ArrayUtil.isEmpty(resources)) {
throw new ConfigErrorException("config error,please check rule source property");
}
allResource.addAll(ListUtil.toList(resources));
}
//如果有多个资源检查资源都是同一个类型如果出现不同类型的配置则抛出错误提示
Set<String> fileTypeSet = new HashSet<>();
allResource.forEach(resource -> fileTypeSet.add(FileUtil.extName(resource.getFilename())));
if (fileTypeSet.size() != 1) {
throw new ConfigErrorException("config error,please use the same type of configuration");
}
return allResource.toArray(new Resource[]{});
}
}

View File

@ -10,17 +10,15 @@ import com.alibaba.fastjson.parser.Feature;
import com.yomahub.liteflow.builder.LiteFlowChainBuilder;
import com.yomahub.liteflow.builder.LiteFlowConditionBuilder;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.EmptyConditionValueException;
import com.yomahub.liteflow.exception.NodeTypeNotSupportException;
import com.yomahub.liteflow.exception.NotSupportConditionException;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.spi.factory.ContextCmpInitFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
@ -29,7 +27,7 @@ import java.util.*;
* @author guodongqing
* @since 2.5.0
*/
public abstract class JsonFlowParser extends FlowParser {
public abstract class JsonFlowParser implements FlowParser {
private final Logger LOG = LoggerFactory.getLogger(JsonFlowParser.class);
@ -55,11 +53,10 @@ public abstract class JsonFlowParser extends FlowParser {
//json格式解析过程
public void parseJsonObject(List<JSONObject> flowJsonObjectList) throws Exception {
for (Map.Entry<String, NodeComponent> componentEntry : ComponentScanner.nodeComponentMap.entrySet()) {
if (!FlowBus.containNode(componentEntry.getKey())) {
FlowBus.addSpringScanNode(componentEntry.getKey(), componentEntry.getValue());
}
}
//在相应的环境下进行节点的初始化工作
//在spring体系下会获得spring扫描后的节点接入元数据
//在非spring体系下是一个空实现等于不做此步骤
ContextCmpInitFactory.loadContextCmpInit().initCmp();
//先在元数据里放上chain
//先放有一个好处可以在parse的时候先映射到FlowBus的chainMap然后再去解析

View File

@ -1,10 +1,6 @@
package com.yomahub.liteflow.parser;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.core.io.Resource;
import com.yomahub.liteflow.spi.factory.PathContentParserFactory;
import java.util.List;
@ -16,14 +12,7 @@ public class LocalJsonFlowParser extends JsonFlowParser{
@Override
public void parseMain(List<String> pathList) throws Exception {
Resource[] resources = matchRuleResources(pathList);
List<String> contentList = ListUtil.toList();
for (Resource resource : resources) {
String content = IoUtil.read(resource.getInputStream(), CharsetUtil.CHARSET_UTF_8);
if (StrUtil.isNotBlank(content)){
contentList.add(content);
}
}
List<String> contentList = PathContentParserFactory.loadContextAware().parseContent(pathList);
parse(contentList);
}
}

View File

@ -7,11 +7,7 @@
*/
package com.yomahub.liteflow.parser;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.core.io.Resource;
import com.yomahub.liteflow.spi.factory.PathContentParserFactory;
import java.util.List;
@ -22,14 +18,7 @@ import java.util.List;
public class LocalXmlFlowParser extends XmlFlowParser{
public void parseMain(List<String> pathList) throws Exception {
Resource[] resources = matchRuleResources(pathList);
List<String> contentList = ListUtil.toList();
for (Resource resource : resources) {
String content = IoUtil.read(resource.getInputStream(), CharsetUtil.CHARSET_UTF_8);
if (StrUtil.isNotBlank(content)){
contentList.add(content);
}
}
List<String> contentList = PathContentParserFactory.loadContextAware().parseContent(pathList);
parse(contentList);
}
}

View File

@ -1,10 +1,6 @@
package com.yomahub.liteflow.parser;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.core.io.Resource;
import com.yomahub.liteflow.spi.factory.PathContentParserFactory;
import java.util.List;
@ -18,14 +14,7 @@ public class LocalYmlFlowParser extends YmlFlowParser {
@Override
public void parseMain(List<String> pathList) throws Exception {
Resource[] resources = matchRuleResources(pathList);
List<String> contentList = ListUtil.toList();
for (Resource resource : resources) {
String content = IoUtil.read(resource.getInputStream(), CharsetUtil.CHARSET_UTF_8);
if (StrUtil.isNotBlank(content)){
contentList.add(content);
}
}
List<String> contentList = PathContentParserFactory.loadContextAware().parseContent(pathList);
parse(contentList);
}

View File

@ -7,27 +7,24 @@ import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.builder.LiteFlowChainBuilder;
import com.yomahub.liteflow.builder.LiteFlowConditionBuilder;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.*;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.spi.factory.ContextCmpInitFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
/**
* xml形式的解析器
* @author Bryan.Zhang
*/
public abstract class XmlFlowParser extends FlowParser {
public abstract class XmlFlowParser implements FlowParser {
private final Logger LOG = LoggerFactory.getLogger(XmlFlowParser.class);
@ -49,12 +46,10 @@ public abstract class XmlFlowParser extends FlowParser {
//xml形式的主要解析过程
public void parseDocument(List<Document> documentList) throws Exception {
//先进行Spring上下文中的节点的判断
for (Entry<String, NodeComponent> componentEntry : ComponentScanner.nodeComponentMap.entrySet()) {
if (!FlowBus.containNode(componentEntry.getKey())) {
FlowBus.addSpringScanNode(componentEntry.getKey(), componentEntry.getValue());
}
}
//在相应的环境下进行节点的初始化工作
//在spring体系下会获得spring扫描后的节点接入元数据
//在非spring体系下是一个空实现等于不做此步骤
ContextCmpInitFactory.loadContextCmpInit().initCmp();
//先在元数据里放上chain
//先放有一个好处可以在parse的时候先映射到FlowBus的chainMap然后再去解析

View File

@ -1,22 +1,31 @@
package com.yomahub.liteflow.property;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.util.SpringAware;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
/**
* liteflow的配置获取器
*/
public class LiteflowConfigGetter {
private static LiteflowConfig liteflowConfig;
public static LiteflowConfig get(){
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
//这里liteflowConfig不可能为null
//如果在springboot环境由于自动装配所以不可能为null
//在spring环境如果xml没配置在FlowExecutor的init时候就已经报错了
//只有在非spring环境下是为null
if (ObjectUtil.isNull(liteflowConfig)){
liteflowConfig = new LiteflowConfig();
liteflowConfig = ContextAwareFactory.loadContextAware().getBean(LiteflowConfig.class);
//这里liteflowConfig不可能为null
//如果在springboot环境由于自动装配所以不可能为null
//在spring环境如果xml没配置在FlowExecutor的init时候就已经报错了
//只有在非spring环境下是为null
if (ObjectUtil.isNull(liteflowConfig)){
liteflowConfig = new LiteflowConfig();
}
}
return liteflowConfig;
}
public static void clean(){
liteflowConfig = null;
}
}

View File

@ -0,0 +1,15 @@
package com.yomahub.liteflow.spi;
import com.yomahub.liteflow.entity.data.Slot;
/**
* 组件全局切面spi接口
* @author Bryan.Zhang
* @since 2.6.11
*/
public interface CmpAroundAspect extends SpiPriority {
void beforeProcess(String nodeId, Slot slot);
void afterProcess(String nodeId, Slot slot);
}

View File

@ -0,0 +1,20 @@
package com.yomahub.liteflow.spi;
/**
* 环境容器SPI接口
*
* @author Bryan.Zhang
* @since 2.6.11
*/
public interface ContextAware extends SpiPriority {
<T> T getBean(String name);
<T> T getBean(Class<T> clazz);
<T> T registerBean(String beanName, Class<T> clazz);
<T> T registerBean(Class<T> clazz);
<T> T registerOrGet(String beanName, Class<T> clazz);
}

View File

@ -0,0 +1,13 @@
package com.yomahub.liteflow.spi;
/**
* 环境容器中组件初始化SPI接口
* 分2个非spring环境下的实现和spring体系下的实现
*
* @author Bryan.Zhang
* @since 2.6.11
*/
public interface ContextCmpInit extends SpiPriority {
void initCmp();
}

View File

@ -0,0 +1,15 @@
package com.yomahub.liteflow.spi;
import com.yomahub.liteflow.core.NodeComponent;
/**
* LiteflowComponent注解处理器SPI接口
*
* @author Bryan.Zhang
* @since 2.6.11
*/
public interface LiteflowComponentSupport extends SpiPriority {
String getCmpName(NodeComponent nodeComponent);
}

View File

@ -0,0 +1,8 @@
package com.yomahub.liteflow.spi;
import java.util.List;
public interface PathContentParser extends SpiPriority{
List<String> parseContent(List<String> pathList) throws Exception;
}

View File

@ -0,0 +1,12 @@
package com.yomahub.liteflow.spi;
/**
* Spi实现的优先级接口
* 数字越小优先级越高
* @author Bryan.Zhang
* @since 2.6.11
*/
public interface SpiPriority {
int priority();
}

View File

@ -0,0 +1,33 @@
package com.yomahub.liteflow.spi.factory;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.spi.CmpAroundAspect;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
/**
* 组件全局拦截器SPI工厂类
* @author Bryan.Zhang
* @since 2.6.11
*/
public class CmpAroundAspectFactory {
private static CmpAroundAspect cmpAroundAspect;
public static CmpAroundAspect loadCmpAroundAspect(){
if (ObjectUtil.isNull(cmpAroundAspect)){
List<CmpAroundAspect> list = new ArrayList<>();
ServiceLoader.load(CmpAroundAspect.class).forEach(list::add);
list.sort(Comparator.comparingInt(CmpAroundAspect::priority));
cmpAroundAspect = list.get(0);
}
return cmpAroundAspect;
}
public static void clean(){
cmpAroundAspect = null;
}
}

View File

@ -0,0 +1,34 @@
package com.yomahub.liteflow.spi.factory;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.spi.ContextAware;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
/**
* 环境容器SPI工厂类
* 在spring体系下会获得spring的上下文包装实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class ContextAwareFactory {
private static ContextAware contextAware;
public static ContextAware loadContextAware(){
if (ObjectUtil.isNull(contextAware)){
List<ContextAware> list = new ArrayList<>();
ServiceLoader.load(ContextAware.class).forEach(list::add);
list.sort(Comparator.comparingInt(ContextAware::priority));
contextAware = list.get(0);
}
return contextAware;
}
public static void clean(){
contextAware = null;
}
}

View File

@ -0,0 +1,33 @@
package com.yomahub.liteflow.spi.factory;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.spi.ContextCmpInit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
/**
* 环境组件初始化SPI工厂类
* 在spring体系下会获得基于spring扫描的组件初始化实现器
* @author Bryan.Zhang
* @since 2.6.11
*/
public class ContextCmpInitFactory {
private static ContextCmpInit contextCmpInit;
public static ContextCmpInit loadContextCmpInit(){
if (ObjectUtil.isNull(contextCmpInit)){
List<ContextCmpInit> list = new ArrayList<>();
ServiceLoader.load(ContextCmpInit.class).forEach(list::add);
list.sort(Comparator.comparingInt(ContextCmpInit::priority));
contextCmpInit = list.get(0);
}
return contextCmpInit;
}
public static void clean(){
contextCmpInit = null;
}
}

View File

@ -0,0 +1,32 @@
package com.yomahub.liteflow.spi.factory;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.spi.LiteflowComponentSupport;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
/**
* liteflowComponent的支持扩展SPI工厂类
* @author Bryan.Zhang
* @since 2.6.11
*/
public class LiteflowComponentSupportFactory {
private static LiteflowComponentSupport liteflowComponentSupport;
public static LiteflowComponentSupport loadLiteflowComponentSupport(){
if (ObjectUtil.isNull(liteflowComponentSupport)){
List<LiteflowComponentSupport> list = new ArrayList<>();
ServiceLoader.load(LiteflowComponentSupport.class).forEach(list::add);
list.sort(Comparator.comparingInt(LiteflowComponentSupport::priority));
liteflowComponentSupport = list.get(0);
}
return liteflowComponentSupport;
}
public static void clean(){
liteflowComponentSupport = null;
}
}

View File

@ -0,0 +1,31 @@
package com.yomahub.liteflow.spi.factory;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.spi.ContextAware;
import com.yomahub.liteflow.spi.PathContentParser;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
public class PathContentParserFactory {
private static PathContentParser pathContentParser;
public static PathContentParser loadContextAware(){
if (ObjectUtil.isNull(pathContentParser)){
List<PathContentParser> list = new ArrayList<>();
ServiceLoader.load(PathContentParser.class).forEach(list::add);
list.sort(Comparator.comparingInt(PathContentParser::priority));
pathContentParser = list.get(0);
}
return pathContentParser;
}
public static void clean(){
pathContentParser = null;
}
}

View File

@ -0,0 +1,12 @@
package com.yomahub.liteflow.spi.factory;
public class SpiFactoryCleaner {
public static void clean(){
CmpAroundAspectFactory.clean();
ContextAwareFactory.clean();
ContextCmpInitFactory.clean();
LiteflowComponentSupportFactory.clean();
PathContentParserFactory.clean();
}
}

View File

@ -0,0 +1,27 @@
package com.yomahub.liteflow.spi.local;
import com.yomahub.liteflow.entity.data.Slot;
import com.yomahub.liteflow.spi.CmpAroundAspect;
/**
* 非Spring环境全局组件切面实现
* 其实非Spring不支持全局组件切面所以这个是个空实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class LocalCmpAroundAspect implements CmpAroundAspect {
@Override
public void beforeProcess(String nodeId, Slot slot) {
//无spring环境下为空实现
}
@Override
public void afterProcess(String nodeId, Slot slot) {
//无spring环境下为空实现
}
@Override
public int priority() {
return 2;
}
}

View File

@ -0,0 +1,42 @@
package com.yomahub.liteflow.spi.local;
import cn.hutool.core.util.ReflectUtil;
import com.yomahub.liteflow.spi.ContextAware;
/**
* 非Spring环境容器实现
* 其实非Spring没有环境容器所以这是个空实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class LocalContextAware implements ContextAware {
@Override
public <T> T getBean(String name) {
return null;
}
@Override
public <T> T getBean(Class<T> clazz) {
return null;
}
@Override
public <T> T registerBean(String beanName, Class<T> clazz) {
return ReflectUtil.newInstance(clazz);
}
@Override
public <T> T registerBean(Class<T> clazz) {
return registerBean(null, clazz);
}
@Override
public <T> T registerOrGet(String beanName, Class<T> clazz) {
return registerBean(beanName, clazz);
}
@Override
public int priority() {
return 2;
}
}

View File

@ -0,0 +1,21 @@
package com.yomahub.liteflow.spi.local;
import com.yomahub.liteflow.spi.ContextCmpInit;
/**
* 非Spring环境容器上下文组件初始化实现
* 其实非Spring没有环境容器所以这是个空实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class LocalContextCmpInit implements ContextCmpInit {
@Override
public void initCmp() {
//非spring环境不用实现
}
@Override
public int priority() {
return 2;
}
}

View File

@ -0,0 +1,22 @@
package com.yomahub.liteflow.spi.local;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.LiteflowComponentSupport;
/**
* 非spring环境LiteflowComponent注解的处理器
* 非spring环境不支持@LiteflowComponent注解所以返回null
* @author Bryan.Zhang
* @since 2.6.11
*/
public class LocalLiteflowComponentSupport implements LiteflowComponentSupport {
@Override
public String getCmpName(NodeComponent nodeComponent) {
return null;
}
@Override
public int priority() {
return 2;
}
}

View File

@ -0,0 +1,44 @@
package com.yomahub.liteflow.spi.local;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import com.yomahub.liteflow.exception.ConfigErrorException;
import com.yomahub.liteflow.spi.PathContentParser;
import java.util.ArrayList;
import java.util.List;
public class LocalPathContentParser implements PathContentParser {
private final static String FILE_URL_PREFIX = "file:";
private final static String CLASSPATH_URL_PREFIX = "classpath:";
@Override
public List<String> parseContent(List<String> pathList) throws Exception {
if(CollectionUtil.isEmpty(pathList)){
throw new ConfigErrorException("rule source must not be null");
}
List<String> contentList = new ArrayList<>();
for(String path : pathList){
if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)){
path = FILE_URL_PREFIX + path;
} else {
if (!path.startsWith(CLASSPATH_URL_PREFIX)) {
path = CLASSPATH_URL_PREFIX + path;
}
}
contentList.add(ResourceUtil.readUtf8Str(path));
}
return contentList;
}
@Override
public int priority() {
return 2;
}
}

View File

@ -1,12 +1,10 @@
package com.yomahub.liteflow.thread;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.util.SpringAware;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
/**
* LiteFlow默认的并行多线程执行器实现
@ -16,7 +14,7 @@ import java.util.concurrent.atomic.AtomicLong;
public class LiteFlowDefaultExecutorBuilder implements ExecutorBuilder{
@Override
public ExecutorService buildExecutor() {
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
//只有在非spring的场景下liteflowConfig才会为null
if (ObjectUtil.isNull(liteflowConfig)){
liteflowConfig = new LiteflowConfig();

View File

@ -1,5 +1,6 @@
package com.yomahub.liteflow.util;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.thread.ExecutorHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -18,7 +19,7 @@ public class LiteFlowExecutorPoolShutdown {
@PreDestroy
public void destroy() throws Exception {
ExecutorService executorService = SpringAware.getBean("whenExecutors");
ExecutorService executorService = ContextAwareFactory.loadContextAware().getBean("whenExecutors");
LOG.info("Start closing the liteflow-when-calls...");
ExecutorHelper.loadInstance().shutdownAwaitTermination(executorService);

View File

@ -0,0 +1,2 @@
# 无Spring的实现
com.yomahub.liteflow.spi.local.LocalCmpAroundAspect

View File

@ -0,0 +1,2 @@
# 无Spring的实现
com.yomahub.liteflow.spi.local.LocalContextAware

View File

@ -0,0 +1,2 @@
# 无Spring的实现
com.yomahub.liteflow.spi.local.LocalContextCmpInit

View File

@ -0,0 +1,2 @@
# 无Spring的实现
com.yomahub.liteflow.spi.local.LocalLiteflowComponentSupport

View File

@ -0,0 +1,2 @@
# 无Spring的实现
com.yomahub.liteflow.spi.local.LocalPathContentParser

View File

@ -16,7 +16,7 @@
<dependencies>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-core</artifactId>
<artifactId>liteflow-spring</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>

View File

@ -1,12 +1,11 @@
package com.yomahub.liteflow.springboot.config;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.monitor.MonitorBus;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.spring.SpringAware;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.springboot.LiteflowExecutorInit;
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;

37
liteflow-spring/pom.xml Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>liteflow</artifactId>
<groupId>com.yomahub</groupId>
<version>2.6.11</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liteflow-spring</artifactId>
<dependencies>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,8 +1,7 @@
package com.yomahub.liteflow.annotation;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**

View File

@ -1,9 +1,9 @@
package com.yomahub.liteflow.util;
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.yomahub.liteflow.spi.ContextAware;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
@ -14,7 +14,7 @@ import org.springframework.context.ApplicationContextAware;
* 基于代码形式的spring上下文工具类
* @author Bryan.Zhang
*/
public class SpringAware implements ApplicationContextAware {
public class SpringAware implements ApplicationContextAware, ContextAware {
private static ApplicationContext applicationContext = null;
@ -29,7 +29,7 @@ public class SpringAware implements ApplicationContextAware {
return applicationContext;
}
public static <T> T getBean(String name) {
public <T> T getBean(String name) {
try{
T t = (T) applicationContext.getBean(name);
return t;
@ -38,7 +38,7 @@ public class SpringAware implements ApplicationContextAware {
}
}
public static <T> T getBean(Class<T> clazz) {
public <T> T getBean(Class<T> clazz) {
try{
T t = applicationContext.getBean(clazz);
return t;
@ -47,7 +47,7 @@ public class SpringAware implements ApplicationContextAware {
}
}
public static <T> T registerBean(String beanName, Class<T> c) {
public <T> T registerBean(String beanName, Class<T> c) {
try{
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
BeanDefinition beanDefinition = new GenericBeanDefinition();
@ -59,18 +59,23 @@ public class SpringAware implements ApplicationContextAware {
}
}
public static <T> T registerBean(Class<T> c) {
public <T> T registerBean(Class<T> c) {
return registerBean(c.getName(), c);
}
public static <T> T registerOrGet(String beanName, Class<T> clazz) {
public <T> T registerOrGet(String beanName, Class<T> clazz) {
if (ObjectUtil.isNull(applicationContext)){
return null;
}
T t = SpringAware.getBean(clazz);
T t = getBean(clazz);
if (ObjectUtil.isNull(t)) {
t = SpringAware.registerBean(beanName, clazz);
t = registerBean(beanName, clazz);
}
return t;
}
@Override
public int priority() {
return 1;
}
}

View File

@ -0,0 +1,32 @@
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.entity.data.Slot;
import com.yomahub.liteflow.spi.CmpAroundAspect;
import com.yomahub.liteflow.spring.ComponentScanner;
/**
* Spring环境全局组件切面实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class SpringCmpAroundAspect implements CmpAroundAspect {
@Override
public void beforeProcess(String nodeId, Slot slot) {
if (ObjectUtil.isNotNull(ComponentScanner.cmpAroundAspect)) {
ComponentScanner.cmpAroundAspect.beforeProcess(nodeId, slot);
}
}
@Override
public void afterProcess(String nodeId, Slot slot) {
if (ObjectUtil.isNotNull(ComponentScanner.cmpAroundAspect)) {
ComponentScanner.cmpAroundAspect.afterProcess(nodeId, slot);
}
}
@Override
public int priority() {
return 1;
}
}

View File

@ -0,0 +1,29 @@
package com.yomahub.liteflow.spi.spring;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.spi.ContextCmpInit;
import com.yomahub.liteflow.spring.ComponentScanner;
import java.util.Map;
/**
* Spring环境容器上下文组件初始化实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class SpringContextCmpInit implements ContextCmpInit {
@Override
public void initCmp() {
for (Map.Entry<String, NodeComponent> componentEntry : ComponentScanner.nodeComponentMap.entrySet()) {
if (!FlowBus.containNode(componentEntry.getKey())) {
FlowBus.addSpringScanNode(componentEntry.getKey(), componentEntry.getValue());
}
}
}
@Override
public int priority() {
return 1;
}
}

View File

@ -0,0 +1,31 @@
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.LiteflowComponentSupport;
/**
* spring环境LiteflowComponent注解的处理器
* @author Bryan.Zhang
* @since 2.6.11
*/
public class SpringLiteflowComponentSupport implements LiteflowComponentSupport {
@Override
public String getCmpName(NodeComponent nodeComponent) {
//判断NodeComponent是否是标识了@LiteflowComponent的标注
//如果标注了那么要从中取到name字段
LiteflowComponent liteflowComponent = nodeComponent.getClass().getAnnotation(LiteflowComponent.class);
if (ObjectUtil.isNotNull(liteflowComponent)) {
return liteflowComponent.name();
}else{
return null;
}
}
@Override
public int priority() {
return 1;
}
}

View File

@ -0,0 +1,74 @@
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.exception.ConfigErrorException;
import com.yomahub.liteflow.spi.PathContentParser;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ResourceUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class SpringPathContentParser implements PathContentParser {
@Override
public List<String> parseContent(List<String> pathList) throws Exception {
if(CollectionUtil.isEmpty(pathList)){
throw new ConfigErrorException("rule source must not be null");
}
List<Resource> allResource = new ArrayList<>();
for (String path : pathList) {
String locationPattern;
//如果path是绝对路径且这个文件存在时我们认为这是一个本地文件路径而并非classpath路径
if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)){
locationPattern = ResourceUtils.FILE_URL_PREFIX + path;
} else {
if (!path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
locationPattern = ResourceUtils.CLASSPATH_URL_PREFIX + path;
}else{
locationPattern = path;
}
}
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources(locationPattern);
if (ArrayUtil.isEmpty(resources)) {
throw new ConfigErrorException("config error,please check rule source property");
}
allResource.addAll(ListUtil.toList(resources));
}
//如果有多个资源检查资源都是同一个类型如果出现不同类型的配置则抛出错误提示
Set<String> fileTypeSet = new HashSet<>();
allResource.forEach(resource -> fileTypeSet.add(FileUtil.extName(resource.getFilename())));
if (fileTypeSet.size() != 1) {
throw new ConfigErrorException("config error,please use the same type of configuration");
}
//转换成内容List
List<String> contentList = new ArrayList<>();
for (Resource resource : allResource) {
String content = IoUtil.read(resource.getInputStream(), CharsetUtil.CHARSET_UTF_8);
if (StrUtil.isNotBlank(content)){
contentList.add(content);
}
}
return contentList;
}
@Override
public int priority() {
return 1;
}
}

View File

@ -11,14 +11,14 @@ package com.yomahub.liteflow.spring;
import com.yomahub.liteflow.aop.ICmpAroundAspect;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.util.LOGOPrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
/**
* 组件扫描类只要是NodeComponent的实现类都可以被这个扫描器扫到

View File

@ -0,0 +1,2 @@
# 无Spring的实现
com.yomahub.liteflow.spi.spring.SpringCmpAroundAspect

View File

@ -0,0 +1,2 @@
# Spring的实现
com.yomahub.liteflow.spi.spring.SpringAware

View File

@ -0,0 +1,2 @@
# Spring的实现
com.yomahub.liteflow.spi.spring.SpringContextCmpInit

View File

@ -0,0 +1,2 @@
# 无Spring的实现
com.yomahub.liteflow.spi.spring.SpringLiteflowComponentSupport

View File

@ -0,0 +1,2 @@
# Spring的实现
com.yomahub.liteflow.spi.spring.SpringPathContentParser

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>liteflow</artifactId>
<groupId>com.yomahub</groupId>
<version>2.6.11</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liteflow-testcase-nospring</artifactId>
<dependencies>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,22 @@
package com.yomahub.liteflow.test.base;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.entity.data.DefaultSlot;
import com.yomahub.liteflow.entity.data.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import org.junit.Assert;
import org.junit.Test;
public class BaseTest {
@Test
public void testBase(){
LiteflowConfig config = new LiteflowConfig();
config.setRuleSource("base/flow.xml");
FlowExecutor executor = new FlowExecutor();
executor.setLiteflowConfig(config);
executor.init();
LiteflowResponse<DefaultSlot> response = executor.execute2Resp("chain1", "test0");
Assert.assertTrue(response.isSuccess());
}
}

View File

@ -0,0 +1,18 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.base.cmp;
import com.yomahub.liteflow.core.NodeComponent;
public class ACmp extends NodeComponent {
@Override
public void process() {
System.out.println("ACmp executed!");
}
}

View File

@ -0,0 +1,19 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.base.cmp;
import com.yomahub.liteflow.core.NodeComponent;
public class BCmp extends NodeComponent {
@Override
public void process() {
System.out.println("BCmp executed!");
}
}

View File

@ -0,0 +1,19 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.base.cmp;
import com.yomahub.liteflow.core.NodeComponent;
public class CCmp extends NodeComponent {
@Override
public void process() {
System.out.println("CCmp executed!");
}
}

View File

@ -0,0 +1,19 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.base.cmp;
import com.yomahub.liteflow.core.NodeComponent;
public class DCmp extends NodeComponent {
@Override
public void process() {
System.out.println("DCmp executed!");
}
}

View File

@ -0,0 +1,18 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.base.cmp;
import com.yomahub.liteflow.core.NodeCondComponent;
public class ECmp extends NodeCondComponent {
@Override
public String processCond() throws Exception {
return "g";
}
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="a" class="com.yomahub.liteflow.test.base.cmp.ACmp"/>
<node id="b" class="com.yomahub.liteflow.test.base.cmp.BCmp"/>
<node id="c" class="com.yomahub.liteflow.test.base.cmp.CCmp"/>
<node id="d" class="com.yomahub.liteflow.test.base.cmp.DCmp"/>
<node id="e" class="com.yomahub.liteflow.test.base.cmp.ECmp"/>
</nodes>
<chain name="chain1">
<when value="a,b,c"/>
<then value="d,e"/>
</chain>
</flow>

View File

@ -1,6 +1,8 @@
package com.yomahub.liteflow.test;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.spi.factory.SpiFactoryCleaner;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.thread.ExecutorHelper;
import org.junit.AfterClass;
@ -12,5 +14,7 @@ public class BaseTest {
ComponentScanner.cleanCache();
FlowBus.cleanCache();
ExecutorHelper.loadInstance().clearExecutorServiceMap();
SpiFactoryCleaner.clean();
LiteflowConfigGetter.clean();
}
}

View File

@ -1,6 +1,8 @@
package com.yomahub.liteflow.test;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.spi.factory.SpiFactoryCleaner;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.thread.ExecutorHelper;
import org.junit.AfterClass;
@ -12,5 +14,7 @@ public class BaseTest {
ComponentScanner.cleanCache();
FlowBus.cleanCache();
ExecutorHelper.loadInstance().clearExecutorServiceMap();
SpiFactoryCleaner.clean();
LiteflowConfigGetter.clean();
}
}

View File

@ -1,7 +1,8 @@
package com.yomahub.liteflow.test;
import com.yomahub.liteflow.entity.data.DataBus;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.spi.factory.SpiFactoryCleaner;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.thread.ExecutorHelper;
import org.junit.AfterClass;
@ -13,5 +14,7 @@ public class BaseTest {
ComponentScanner.cleanCache();
FlowBus.cleanCache();
ExecutorHelper.loadInstance().clearExecutorServiceMap();
SpiFactoryCleaner.clean();
LiteflowConfigGetter.clean();
}
}

View File

@ -3,7 +3,6 @@ package com.yomahub.liteflow.test.aop;
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.spring.ComponentScanner;
import com.yomahub.liteflow.test.BaseTest;
import com.yomahub.liteflow.test.aop.aspect.CmpAspect;

View File

@ -1,19 +1,17 @@
package com.yomahub.liteflow.test.customWhenThreadPool;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.thread.ExecutorBuilder;
import com.yomahub.liteflow.util.SpringAware;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
public class CustomThreadExecutor1 implements ExecutorBuilder {
@Override
public ExecutorService buildExecutor() {
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = ContextAwareFactory.loadContextAware().getBean(LiteflowConfig.class);
//只有在非spring的场景下liteflowConfig才会为null
if (ObjectUtil.isNull(liteflowConfig)) {
liteflowConfig = new LiteflowConfig();

View File

@ -1,18 +1,16 @@
package com.yomahub.liteflow.test.customWhenThreadPool;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.thread.ExecutorBuilder;
import com.yomahub.liteflow.util.SpringAware;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
public class CustomThreadExecutor2 implements ExecutorBuilder {
@Override
public ExecutorService buildExecutor() {
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = ContextAwareFactory.loadContextAware().getBean(LiteflowConfig.class);
//只有在非spring的场景下liteflowConfig才会为null
if (ObjectUtil.isNull(liteflowConfig)) {
liteflowConfig = new LiteflowConfig();

View File

@ -2,15 +2,15 @@ package com.yomahub.liteflow.test.customWhenThreadPool;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.thread.ExecutorBuilder;
import com.yomahub.liteflow.util.SpringAware;
import java.util.concurrent.ExecutorService;
public class CustomThreadExecutor3 implements ExecutorBuilder {
@Override
public ExecutorService buildExecutor() {
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = ContextAwareFactory.loadContextAware().getBean(LiteflowConfig.class);
//只有在非spring的场景下liteflowConfig才会为null
if (ObjectUtil.isNull(liteflowConfig)) {
liteflowConfig = new LiteflowConfig();

View File

@ -14,7 +14,6 @@ import org.springframework.stereotype.Component;
import java.util.HashSet;
@Component("a")
@LiteflowComponent("a")
public class ACmp extends NodeComponent {

View File

@ -13,7 +13,6 @@ import org.springframework.stereotype.Component;
import java.util.Set;
@Component("b")
@LiteflowComponent("b")
public class BCmp extends NodeComponent {

View File

@ -9,7 +9,6 @@ package com.yomahub.liteflow.test.privateDelivery.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@LiteflowComponent("c")
public class CCmp extends NodeComponent {

View File

@ -39,6 +39,8 @@ public class ReloadSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
//用reloadRule去重新加载这里如果配置是放在本地如果想修改则要去修改target下面的flow.xml
//这里的测试手动打断点然后去修改是ok的但是整个测试暂且只是为了测试这个功能是否能正常运行
@Test
public void testReload() throws Exception{
flowExecutor.reloadRule();

View File

@ -11,8 +11,6 @@ import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.entity.data.Slot;
import java.util.HashSet;
@LiteflowComponent("a")
public class ACmp extends NodeComponent {

View File

@ -12,10 +12,6 @@ import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.entity.data.Slot;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@LiteflowComponent("b1")
public class B1Cmp extends NodeComponent {

View File

@ -12,9 +12,6 @@ import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.entity.data.Slot;
import java.util.HashSet;
import java.util.Set;
@LiteflowComponent("b")
public class BCmp extends NodeComponent {

View File

@ -8,7 +8,6 @@
package com.yomahub.liteflow.test.tag.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.core.NodeCondComponent;
@LiteflowComponent("c")

View File

@ -14,7 +14,7 @@
<dependencies>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-core</artifactId>
<artifactId>liteflow-spring</artifactId>
<version>${project.version}</version>
</dependency>

View File

@ -1,6 +1,8 @@
package com.yomahub.liteflow.test;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.spi.factory.SpiFactoryCleaner;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.thread.ExecutorHelper;
import org.junit.AfterClass;
@ -12,5 +14,7 @@ public class BaseTest {
ComponentScanner.cleanCache();
FlowBus.cleanCache();
ExecutorHelper.loadInstance().clearExecutorServiceMap();
SpiFactoryCleaner.clean();
LiteflowConfigGetter.clean();
}
}

View File

@ -2,8 +2,8 @@ package com.yomahub.liteflow.test.customWhenThreadPool;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.thread.ExecutorBuilder;
import com.yomahub.liteflow.util.SpringAware;
import java.util.concurrent.ExecutorService;
@ -11,7 +11,7 @@ public class CustomThreadExecutor1 implements ExecutorBuilder {
@Override
public ExecutorService buildExecutor() {
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = ContextAwareFactory.loadContextAware().getBean(LiteflowConfig.class);
//只有在非spring的场景下liteflowConfig才会为null
if (ObjectUtil.isNull(liteflowConfig)) {
liteflowConfig = new LiteflowConfig();

View File

@ -2,15 +2,15 @@ package com.yomahub.liteflow.test.customWhenThreadPool;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.thread.ExecutorBuilder;
import com.yomahub.liteflow.util.SpringAware;
import java.util.concurrent.ExecutorService;
public class CustomThreadExecutor2 implements ExecutorBuilder {
@Override
public ExecutorService buildExecutor() {
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = ContextAwareFactory.loadContextAware().getBean(LiteflowConfig.class);
//只有在非spring的场景下liteflowConfig才会为null
if (ObjectUtil.isNull(liteflowConfig)) {
liteflowConfig = new LiteflowConfig();

View File

@ -2,15 +2,15 @@ package com.yomahub.liteflow.test.customWhenThreadPool;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.spi.factory.ContextAwareFactory;
import com.yomahub.liteflow.thread.ExecutorBuilder;
import com.yomahub.liteflow.util.SpringAware;
import java.util.concurrent.ExecutorService;
public class CustomThreadExecutor3 implements ExecutorBuilder {
@Override
public ExecutorService buildExecutor() {
LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class);
LiteflowConfig liteflowConfig = ContextAwareFactory.loadContextAware().getBean(LiteflowConfig.class);
//只有在非spring的场景下liteflowConfig才会为null
if (ObjectUtil.isNull(liteflowConfig)) {
liteflowConfig = new LiteflowConfig();

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.config.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.config.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.customThreadPool.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.customWhenThreadPool.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.enable.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.nullParam.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.parser.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.parser.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.parser.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.zookeeper.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.zookeeper.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -9,7 +9,7 @@
<context:component-scan base-package="com.yomahub.liteflow.test.zookeeper.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>

View File

@ -253,7 +253,9 @@
<module>liteflow-testcase-springnative</module>
<module>liteflow-testcase-script-qlexpress</module>
<module>liteflow-testcase-script-groovy</module>
</modules>
<module>liteflow-testcase-nospring</module>
<module>liteflow-spring</module>
</modules>
<distributionManagement>
<snapshotRepository>