All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yomahub.liteflow.flow.FlowBus Maven / Gradle / Ivy

The newest version!
/**
 * 

Title: liteflow

*

Description: 轻量级的组件式流程框架

* * @author Bryan.Zhang * @email [email protected] * @Date 2020/4/1 */ package com.yomahub.liteflow.flow; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.annotation.FallbackCmp; import com.yomahub.liteflow.annotation.util.AnnoUtil; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.core.ComponentInitializer; import com.yomahub.liteflow.core.NodeComponent; import com.yomahub.liteflow.core.ScriptComponent; import com.yomahub.liteflow.core.proxy.DeclWarpBean; import com.yomahub.liteflow.enums.FlowParserTypeEnum; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.exception.ComponentCannotRegisterException; import com.yomahub.liteflow.exception.NullNodeTypeException; import com.yomahub.liteflow.flow.element.Chain; import com.yomahub.liteflow.flow.element.Condition; import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.lifecycle.LifeCycleHolder; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.el.LocalJsonFlowELParser; import com.yomahub.liteflow.parser.el.LocalXmlFlowELParser; import com.yomahub.liteflow.parser.el.LocalYmlFlowELParser; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.script.ScriptExecutorFactory; import com.yomahub.liteflow.script.exception.ScriptLoadException; import com.yomahub.liteflow.script.exception.ScriptSpiException; import com.yomahub.liteflow.spi.ContextAware; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import com.yomahub.liteflow.spi.holder.DeclComponentParserHolder; import com.yomahub.liteflow.util.CopyOnWriteHashMap; import com.yomahub.liteflow.core.proxy.LiteFlowProxyUtil; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; /** * 流程元数据类 * * @author Bryan.Zhang * @author DaleLee */ public class FlowBus { private static final LFLog LOG = LFLoggerManager.getLogger(FlowBus.class); private static final Map chainMap; private static final Map nodeMap; private static final Map fallbackNodeMap; private static final AtomicBoolean initStat = new AtomicBoolean(false); static { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); if (liteflowConfig.getFastLoad()){ chainMap = new HashMap<>(); nodeMap = new HashMap<>(); fallbackNodeMap = new HashMap<>(); }else{ chainMap = new CopyOnWriteHashMap<>(); nodeMap = new CopyOnWriteHashMap<>(); fallbackNodeMap = new CopyOnWriteHashMap<>(); } } public static Chain getChain(String id) { return chainMap.get(id); } // 这一方法主要用于第一阶段chain的预装载 public static void addChain(String chainName) { if (!chainMap.containsKey(chainName)) { chainMap.put(chainName, new Chain(chainName)); } } // 这个方法主要用于第二阶段的替换chain public static void addChain(Chain chain) { //如果有生命周期则执行相应生命周期实现 if (CollUtil.isNotEmpty(LifeCycleHolder.getPostProcessChainBuildLifeCycleList())){ LifeCycleHolder.getPostProcessChainBuildLifeCycleList().forEach( postProcessAfterChainBuildLifeCycle -> postProcessAfterChainBuildLifeCycle.postProcessBeforeChainBuild(chain) ); } chainMap.put(chain.getChainId(), chain); //如果有生命周期则执行相应生命周期实现 if (CollUtil.isNotEmpty(LifeCycleHolder.getPostProcessChainBuildLifeCycleList())){ LifeCycleHolder.getPostProcessChainBuildLifeCycleList().forEach( postProcessAfterChainBuildLifeCycle -> postProcessAfterChainBuildLifeCycle.postProcessAfterChainBuild(chain) ); } } public static boolean containChain(String chainId) { return chainMap.containsKey(chainId); } public static boolean needInit() { return initStat.compareAndSet(false, true); } public static boolean containNode(String nodeId) { return nodeMap.containsKey(nodeId); } public static void addManagedNode(String nodeId) { ContextAware contextAware = ContextAwareHolder.loadContextAware(); if (contextAware.hasBean(nodeId)){ addManagedNode(nodeId, contextAware.getBean(nodeId)); } } /** * 添加已托管的节点(如:Spring、Solon 管理的节点) * */ public static void addManagedNode(String nodeId, NodeComponent nodeComponent) { // 根据class来猜测类型 NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass()); if (type == null) { throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId)); } Node node = new Node(ComponentInitializer.loadInstance() .initComponent(nodeComponent, type, nodeComponent.getName(), nodeId)); put2NodeMap(nodeId, node); addFallbackNode(node); } /** * 添加 node * @param nodeId 节点id * @param name 节点名称 * @param type 节点类型 * @param cmpClazz 节点组件类 */ public static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz) { addNode(nodeId, name, type, cmpClazz, null, null); } /** * 添加 node * @param nodeId 节点id * @param name 节点名称 * @param nodeType 节点类型 * @param cmpClazzStr 节点组件类路径 */ public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr) { Class cmpClazz; try { cmpClazz = Class.forName(cmpClazzStr); } catch (Exception e) { throw new ComponentCannotRegisterException(e.getMessage()); } addNode(nodeId, name, nodeType, cmpClazz, null, null); } /** * 添加脚本 node * @param nodeId 节点id * @param name 节点名称 * @param nodeType 节点类型 * @param script 脚本 */ public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script, String language) { addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script, language); } private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script, String language) { try { // 判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 // 如果不是声明式的,就用传统的方式进行判断 List cmpInstanceList = new ArrayList<>(); if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) { // 如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中 // 由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了 // 所以spring体系下,无需再对这个bean做二次代理 // 非spring体系下,从2.11.4开始不再支持声明式组件 List declWarpBeanList = DeclComponentParserHolder.loadDeclComponentParser().parseDeclBean(cmpClazz, nodeId, name); cmpInstanceList = declWarpBeanList.stream().map( declWarpBean -> (NodeComponent)ContextAwareHolder.loadContextAware().registerDeclWrapBean(nodeId, declWarpBean) ).collect(Collectors.toList()); } else { // 以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置 // 这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了 // 如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance if (!type.isScript()) { cmpInstanceList = ListUtil .toList((NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz)); } // 如果为空 if (cmpInstanceList.isEmpty()) { NodeComponent cmpInstance = (NodeComponent) cmpClazz.newInstance(); cmpInstanceList.add(cmpInstance); } } // 进行初始化component cmpInstanceList = cmpInstanceList.stream() .map(cmpInstance -> ComponentInitializer.loadInstance() .initComponent(cmpInstance, type, name, cmpInstance.getNodeId() == null ? nodeId : cmpInstance.getNodeId())) .collect(Collectors.toList()); // 初始化Node,把component放到Node里去 List nodes = cmpInstanceList.stream().map(Node::new).collect(Collectors.toList()); for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); NodeComponent cmpInstance = cmpInstanceList.get(i); // 如果是脚本节点,则还要加载script脚本 if (type.isScript()) { if (StrUtil.isNotBlank(script)) { node.setScript(script); node.setLanguage(language); ((ScriptComponent) cmpInstance).loadScript(script, language); } else { String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId); throw new ScriptLoadException(errorMsg); } } String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId(); put2NodeMap(activeNodeId, node); addFallbackNode(node); } } catch (Exception e) { String error = StrUtil.format("component[{}] register error", StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name)); LOG.error(e.getMessage()); throw new ComponentCannotRegisterException(StrUtil.format("{} {}", error, e.getMessage())); } } public static Node getNode(String nodeId) { return nodeMap.get(nodeId); } // 获取某一个 chainId 下的所有 nodeId public static List getNodesByChainId(String chainId) { Chain chain = getChain(chainId); return chain.getConditionList().stream().flatMap( (Function>) condition -> condition.getAllNodeInCondition().stream() ).collect(Collectors.toList()); } public static Map getNodeMap() { return nodeMap; } public static Map getChainMap() { return chainMap; } public static Node getFallBackNode(NodeTypeEnum nodeType){ String key = StrUtil.format("FB_{}", nodeType.name()); return fallbackNodeMap.get(key); } public static void cleanCache() { chainMap.clear(); nodeMap.clear(); fallbackNodeMap.clear(); cleanScriptCache(); } public static void cleanScriptCache() { // 如果引入了脚本组件SPI,则还需要清理脚本的缓存 try { ScriptExecutorFactory.loadInstance().cleanScriptCache(); } catch (ScriptSpiException ignored) { } } public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { if (type.equals(FlowParserTypeEnum.TYPE_EL_XML)) { new LocalXmlFlowELParser().parse(content); } else if (type.equals(FlowParserTypeEnum.TYPE_EL_JSON)) { new LocalJsonFlowELParser().parse(content); } else if (type.equals(FlowParserTypeEnum.TYPE_EL_YML)) { new LocalYmlFlowELParser().parse(content); } } public static boolean removeChain(String chainId) { if (containChain(chainId)) { chainMap.remove(chainId); return true; } else { String errMsg = StrUtil.format("cannot find the chain[{}]", chainId); LOG.error(errMsg); return false; } } public static void removeChain(String... chainIds) { Arrays.stream(chainIds).forEach(FlowBus::removeChain); } // 移除节点 public static boolean removeNode(String nodeId) { return nodeMap.remove(nodeId) != null; } // 判断是否是降级组件,如果是则添加到 fallbackNodeMap private static void addFallbackNode(Node node) { NodeComponent nodeComponent = node.getInstance(); FallbackCmp fallbackCmp = AnnoUtil.getAnnotation(nodeComponent.getClass(), FallbackCmp.class); if (fallbackCmp == null) { return; } NodeTypeEnum nodeType = node.getType(); String key = StrUtil.format("FB_{}", nodeType.name()); fallbackNodeMap.put(key, node); } // 重新加载脚本 public static void reloadScript(String nodeId, String script) { Node node = getNode(nodeId); if (node == null || !node.getType().isScript()) { return; } // 更新脚本 node.setScript(script); ScriptExecutorFactory.loadInstance() .getScriptExecutor(node.getLanguage()) .load(nodeId, script); } // 卸载脚本节点 public static boolean unloadScriptNode(String nodeId) { Node node = getNode(nodeId); if (node == null || !node.getType().isScript()) { return false; } // 卸载脚本 ScriptExecutorFactory.loadInstance() .getScriptExecutor(node.getLanguage()) .unLoad(nodeId); // 移除脚本 return removeNode(nodeId); } // 重新加载规则 public static void reloadChain(String chainId, String elContent) { reloadChain(chainId, elContent, null); } public static void reloadChain(String chainId, String elContent, String routeContent) { LiteFlowChainELBuilder.createChain().setChainId(chainId).setEL(elContent).setRoute(routeContent).build(); } public static void clearStat(){ initStat.set(false); } private static void put2NodeMap(String nodeId, Node node){ // 如果有生命周期则执行相应生命周期实现 if (CollUtil.isNotEmpty(LifeCycleHolder.getPostProcessNodeBuildLifeCycleList())){ LifeCycleHolder.getPostProcessNodeBuildLifeCycleList().forEach( postProcessAfterNodeBuildLifeCycle -> postProcessAfterNodeBuildLifeCycle.postProcessBeforeNodeBuild(node) ); } nodeMap.put(nodeId, node); // 如果有生命周期则执行相应生命周期实现 if (CollUtil.isNotEmpty(LifeCycleHolder.getPostProcessNodeBuildLifeCycleList())){ LifeCycleHolder.getPostProcessNodeBuildLifeCycleList().forEach( postProcessAfterNodeBuildLifeCycle -> postProcessAfterNodeBuildLifeCycle.postProcessAfterNodeBuild(node) ); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy