改造 LiteflowMethod 代理处理,采用内核的通用代码

This commit is contained in:
noear
2024-09-03 21:50:04 +08:00
parent 6323f51183
commit 8822ce5bff
7 changed files with 170 additions and 344 deletions

View File

@@ -1,52 +0,0 @@
package com.yomahub.liteflow.solon;
import com.yomahub.liteflow.core.NodeBooleanComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.exception.LiteFlowException;
import org.noear.solon.core.BeanWrap;
import java.lang.reflect.Method;
/**
* @author noear
* @since 1.11
*/
public class NodeBooleanComponentOfMethod extends NodeBooleanComponent {
private final BeanWrap beanWrap;
private final Method method;
private final LiteFlowMethodEnum methodEnum;
public NodeBooleanComponentOfMethod(BeanWrap beanWrap, Method method, LiteFlowMethodEnum methodEnum) {
this.beanWrap = beanWrap;
this.method = method;
this.methodEnum = methodEnum;
if (method.getParameterCount() > 1) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeIfComponent method parameter cannot be more than one: " + methodFullName);
}
if (method.getReturnType() != Boolean.class && method.getReturnType() != boolean.class) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeIfComponent method returnType can only be boolean: " + methodFullName);
}
}
private Object exec() throws Exception {
if (method.getParameterCount() == 0) {
return method.invoke(beanWrap.get());
}
else {
return method.invoke(beanWrap.get(), this);
}
}
@Override
public boolean processBoolean() throws Exception {
return (boolean) exec();
}
}

View File

@@ -1,109 +0,0 @@
package com.yomahub.liteflow.solon;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.exception.LiteFlowException;
import com.yomahub.liteflow.slot.Slot;
import org.noear.solon.core.BeanWrap;
import java.lang.reflect.Method;
/**
* @author noear
* @since 1.11
*/
public class NodeComponentOfMethod extends NodeComponent {
private final BeanWrap beanWrap;
private final Method method;
private final LiteFlowMethodEnum methodEnum;
public NodeComponentOfMethod(BeanWrap beanWrap, Method method, LiteFlowMethodEnum methodEnum) {
this.beanWrap = beanWrap;
this.method = method;
this.methodEnum = methodEnum;
if (method.getParameterCount() > 1) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeComponent method parameter cannot be more than one: " + methodFullName);
}
if (method.getReturnType() != Void.class && method.getReturnType() != void.class) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeComponent method returnType can only be void: " + methodFullName);
}
}
private void exec() throws Exception {
if (method.getParameterCount() == 0) {
method.invoke(beanWrap.get());
}
else {
method.invoke(beanWrap.get(), this);
}
}
@Override
public void process() throws Exception {
if (methodEnum != LiteFlowMethodEnum.PROCESS) {
return;
}
exec();
}
@Override
public void beforeProcess() {
if (methodEnum != LiteFlowMethodEnum.BEFORE_PROCESS) {
return;
}
try {
exec();
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void afterProcess() {
if (methodEnum != LiteFlowMethodEnum.AFTER_PROCESS) {
return;
}
try {
exec();
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void onError(Exception e) throws Exception {
if (methodEnum != LiteFlowMethodEnum.ON_ERROR) {
return;
}
exec();
}
@Override
public void onSuccess() throws Exception {
if (methodEnum != LiteFlowMethodEnum.ON_SUCCESS) {
return;
}
exec();
}
}

View File

@@ -1,52 +0,0 @@
package com.yomahub.liteflow.solon;
import com.yomahub.liteflow.core.NodeForComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.exception.LiteFlowException;
import org.noear.solon.core.BeanWrap;
import java.lang.reflect.Method;
/**
* @author noear
* @since 1.11
*/
public class NodeForComponentOfMethod extends NodeForComponent {
private final BeanWrap beanWrap;
private final Method method;
private final LiteFlowMethodEnum methodEnum;
public NodeForComponentOfMethod(BeanWrap beanWrap, Method method, LiteFlowMethodEnum methodEnum) {
this.beanWrap = beanWrap;
this.method = method;
this.methodEnum = methodEnum;
if (method.getParameterCount() > 1) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeForComponent method parameter cannot be more than one: " + methodFullName);
}
if (method.getReturnType() != Integer.class && method.getReturnType() != int.class) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeForComponent method returnType can only be int: " + methodFullName);
}
}
private Object exec() throws Exception {
if (method.getParameterCount() == 0) {
return method.invoke(beanWrap.get());
}
else {
return method.invoke(beanWrap.get(), this);
}
}
@Override
public int processFor() throws Exception {
return (int) exec();
}
}

View File

@@ -1,49 +0,0 @@
package com.yomahub.liteflow.solon;
import com.yomahub.liteflow.core.NodeIteratorComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.exception.LiteFlowException;
import org.noear.solon.core.BeanWrap;
import java.lang.reflect.Method;
import java.util.Iterator;
/**
* @author noear
*/
public class NodeIteratorComponentOfMethod extends NodeIteratorComponent {
private final BeanWrap beanWrap;
private final Method method;
private final LiteFlowMethodEnum methodEnum;
public NodeIteratorComponentOfMethod(BeanWrap beanWrap, Method method, LiteFlowMethodEnum methodEnum) {
this.beanWrap = beanWrap;
this.method = method;
this.methodEnum = methodEnum;
if (method.getParameterCount() > 1) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeIfComponent method parameter cannot be more than one: " + methodFullName);
}
if (method.getReturnType() != Iterator.class) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeIfComponent method returnType can only be iterator: " + methodFullName);
}
}
private Object exec() throws Exception {
if (method.getParameterCount() == 0) {
return method.invoke(beanWrap.get());
} else {
return method.invoke(beanWrap.get(), this);
}
}
@Override
public Iterator<?> processIterator() throws Exception {
return (Iterator<?>) exec();
}
}

View File

@@ -1,53 +0,0 @@
package com.yomahub.liteflow.solon;
import com.yomahub.liteflow.core.NodeSwitchComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.exception.LiteFlowException;
import org.noear.solon.core.BeanWrap;
import java.lang.reflect.Method;
/**
* @author noear
* @since 1.11
*/
public class NodeSwitchComponentOfMethod extends NodeSwitchComponent {
private final BeanWrap beanWrap;
private final Method method;
private final LiteFlowMethodEnum methodEnum;
public NodeSwitchComponentOfMethod(BeanWrap beanWrap, Method method, LiteFlowMethodEnum methodEnum) {
this.beanWrap = beanWrap;
this.method = method;
this.methodEnum = methodEnum;
if (method.getParameterCount() > 1) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException(
"NodeSwitchComponent method parameter cannot be more than one: " + methodFullName);
}
if (method.getReturnType() != String.class) {
String methodFullName = beanWrap.clz().getName() + "::" + method.getName();
throw new LiteFlowException("NodeSwitchComponent method returnType can only be string: " + methodFullName);
}
}
private Object exec() throws Exception {
if (method.getParameterCount() == 0) {
return method.invoke(beanWrap.get());
}
else {
return method.invoke(beanWrap.get(), this);
}
}
@Override
public String processSwitch() throws Exception {
return (String) exec();
}
}

View File

@@ -3,17 +3,19 @@ package com.yomahub.liteflow.solon.integration;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.core.proxy.DeclWarpBean;
import com.yomahub.liteflow.core.proxy.LiteFlowProxyUtil;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.solon.*;
import com.yomahub.liteflow.solon.config.LiteflowAutoConfiguration;
import com.yomahub.liteflow.solon.config.LiteflowMainAutoConfiguration;
import com.yomahub.liteflow.solon.config.LiteflowMonitorProperty;
import com.yomahub.liteflow.solon.config.LiteflowProperty;
import com.yomahub.liteflow.spi.holder.DeclComponentParserHolder;
import org.noear.solon.Utils;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.Plugin;
import java.util.Properties;
import java.util.*;
/**
* @author noear
@@ -52,30 +54,23 @@ public class XPluginImpl implements Plugin {
FlowBus.addManagedNode(bw.name(), bw.raw());
});
Set<Class<?>> liteflowMethodClassSet = new HashSet<>();
context.beanExtractorAdd(LiteflowMethod.class, (bw, method, anno) -> {
NodeComponent node1 = null;
switch (anno.value()) {
case PROCESS_SWITCH:
node1 = new NodeSwitchComponentOfMethod(bw, method, anno.value());
break;
case PROCESS_BOOLEAN:
node1 = new NodeBooleanComponentOfMethod(bw, method, anno.value());
break;
case PROCESS_FOR:
node1 = new NodeForComponentOfMethod(bw, method, anno.value());
break;
case PROCESS_ITERATOR:
node1 = new NodeIteratorComponentOfMethod(bw, method, anno.value());
break;
default:
node1 = new NodeComponentOfMethod(bw, method, anno.value());
if (liteflowMethodClassSet.contains(bw.clz())) {
return;
} else {
liteflowMethodClassSet.add(bw.clz());
}
String nodeId = Utils.annoAlias(anno.nodeId(), bw.name());
node1.setNodeId(nodeId);
node1.setType(anno.nodeType());
List<DeclWarpBean> declWarpBeanList = DeclComponentParserHolder
.loadDeclComponentParser()
.parseDeclBean(bw.clz());
FlowBus.addManagedNode(nodeId, node1);
for (DeclWarpBean declWarpBean : declWarpBeanList) {
NodeComponent node1 = LiteFlowProxyUtil.proxy2NodeComponent(declWarpBean);
FlowBus.addManagedNode(node1.getNodeId(), node1);
}
});
context.beanBuilderAdd(LiteflowComponent.class, (clz, bw, anno) -> {
@@ -87,11 +82,9 @@ public class XPluginImpl implements Plugin {
node1.setName(anno.name());
FlowBus.addManagedNode(nodeId, node1);
}
else {
} else {
context.beanExtractOrProxy(bw); // 尝试提取 LiteflowMethod 函数,并支持自动代理
}
});
}
}
}

View File

@@ -1,10 +1,26 @@
package com.yomahub.liteflow.spi.solon;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.annotation.*;
import com.yomahub.liteflow.annotation.util.AnnoUtil;
import com.yomahub.liteflow.core.proxy.DeclWarpBean;
import com.yomahub.liteflow.core.proxy.MethodWrapBean;
import com.yomahub.liteflow.core.proxy.ParameterWrapBean;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.CmpDefinitionException;
import com.yomahub.liteflow.exception.NotSupportDeclException;
import com.yomahub.liteflow.spi.DeclComponentParser;
import org.noear.solon.Solon;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.BeanWrap;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Solon 环境声明式组件解析器实现(在 solon 里没有用上;机制不同)
@@ -14,16 +30,148 @@ import java.util.List;
public class SolonDeclComponentParser implements DeclComponentParser {
@Override
public List<DeclWarpBean> parseDeclBean(Class<?> clazz) {
throw new NotSupportDeclException("the declaration component is not supported in solon environment.");
return parseDeclBean(clazz, null, null);
}
@Override
public List<DeclWarpBean> parseDeclBean(Class<?> clazz, String nodeId, String nodeName) {
throw new NotSupportDeclException("the declaration component is not supported in solon environment.");
public List<DeclWarpBean> parseDeclBean(Class<?> clazz, final String nodeId, final String nodeName) {
Map<String, List<DeclInfo>> definitionMap = Arrays.stream(clazz.getMethods()).filter(
method -> AnnotationUtil.getAnnotation(method, LiteflowMethod.class) != null
).map(method -> {
LiteflowMethod liteflowMethod = AnnotationUtil.getAnnotation(method, LiteflowMethod.class);
LiteflowRetry liteflowRetry = AnnotationUtil.getAnnotation(method, LiteflowRetry.class);
String currNodeId = null;
String currNodeName = null;
if (nodeId == null){
if (StrUtil.isBlank(liteflowMethod.nodeId())){
LiteflowComponent liteflowComponent = AnnoUtil.getAnnotation(clazz, LiteflowComponent.class);
Component component = AnnoUtil.getAnnotation(clazz, Component.class);
if(liteflowComponent != null){
currNodeId = liteflowComponent.value();
currNodeName = liteflowComponent.name();
}else if(component != null){
currNodeId = component.value();
}else{
currNodeName = StrUtil.EMPTY;
currNodeId = StrUtil.EMPTY;
}
}else{
currNodeId = liteflowMethod.nodeId();
currNodeName = liteflowMethod.nodeName();
}
}else{
currNodeId = nodeId;
currNodeName = nodeName;
}
NodeTypeEnum nodeType;
LiteflowCmpDefine liteflowCmpDefine = AnnotationUtil.getAnnotation(method.getDeclaringClass(), LiteflowCmpDefine.class);
if (liteflowCmpDefine != null){
nodeType = liteflowCmpDefine.value();
}else{
nodeType = liteflowMethod.nodeType();
}
Parameter[] parameters = method.getParameters();
List<ParameterWrapBean> parameterList = IntStream.range(0, parameters.length).boxed().map(index -> {
Parameter parameter = parameters[index];
return new ParameterWrapBean(parameter.getType(), AnnotationUtil.getAnnotation(parameter, LiteflowFact.class), index);
}).collect(Collectors.toList());
return new DeclInfo(currNodeId, currNodeName, nodeType, method.getDeclaringClass(), new MethodWrapBean(method, liteflowMethod, liteflowRetry, parameterList));
}).filter(declInfo -> StrUtil.isNotBlank(declInfo.getNodeId())).collect(Collectors.groupingBy(DeclInfo::getNodeId));
return definitionMap.entrySet().stream().map(entry -> {
String key = entry.getKey();
List<DeclInfo> declInfos = entry.getValue();
DeclWarpBean declWarpBean = new DeclWarpBean();
declWarpBean.setNodeId(key);
DeclInfo processMethodDeclInfo = declInfos.stream().filter(declInfo -> declInfo.getMethodWrapBean().getLiteflowMethod().value().isMainMethod()).findFirst().orElse(null);
if (processMethodDeclInfo == null){
throw new CmpDefinitionException(StrUtil.format("Component [{}] does not define the process method", key));
}
declWarpBean.setNodeName(processMethodDeclInfo.getNodeName());
declWarpBean.setRawClazz(processMethodDeclInfo.getRawClazz());
declWarpBean.setNodeType(processMethodDeclInfo.getNodeType());
Object rawClassDefinition = Solon.context().getBeanOrNew(clazz);
declWarpBean.setRawBean(rawClassDefinition);
declWarpBean.setMethodWrapBeanList(declInfos.stream().map(DeclInfo::getMethodWrapBean).collect(Collectors.toList()));
return declWarpBean;
}).collect(Collectors.toList());
}
@Override
public int priority() {
return 1;
}
public static class DeclInfo{
private String nodeId;
private String nodeName;
private NodeTypeEnum nodeType;
private Class<?> rawClazz;
private MethodWrapBean methodWrapBean;
public DeclInfo(String nodeId, String nodeName, NodeTypeEnum nodeType, Class<?> rawClazz, MethodWrapBean methodWrapBean) {
this.nodeId = nodeId;
this.nodeName = nodeName;
this.nodeType = nodeType;
this.rawClazz = rawClazz;
this.methodWrapBean = methodWrapBean;
}
public String getNodeId() {
return nodeId;
}
public void setNodeId(String nodeId) {
this.nodeId = nodeId;
}
public Class<?> getRawClazz() {
return rawClazz;
}
public void setRawClazz(Class<?> rawClazz) {
this.rawClazz = rawClazz;
}
public String getNodeName() {
return nodeName;
}
public void setNodeName(String nodeName) {
this.nodeName = nodeName;
}
public MethodWrapBean getMethodWrapBean() {
return methodWrapBean;
}
public void setMethodWrapBean(MethodWrapBean methodWrapBean) {
this.methodWrapBean = methodWrapBean;
}
public NodeTypeEnum getNodeType() {
return nodeType;
}
public void setNodeType(NodeTypeEnum nodeType) {
this.nodeType = nodeType;
}
}
}