mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 20:22:07 +08:00
!147 feat #I64L3Q 增加 @ScriptMethod 注解
Merge pull request !147 from 与或非/issues/I64L3Q
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package com.yomahub.liteflow.script.annotation;
|
||||
|
||||
import com.yomahub.liteflow.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 用于标注在Script中可使用的java 方法
|
||||
*
|
||||
* @author tangkc
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface ScriptMethod {
|
||||
|
||||
@AliasFor("name")
|
||||
String value() default "";
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.yomahub.liteflow.script.proxy;
|
||||
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.exception.LiteFlowException;
|
||||
import com.yomahub.liteflow.exception.ScriptBeanMethodInvokeException;
|
||||
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
|
||||
import com.yomahub.liteflow.util.SerialsUtil;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.implementation.InvocationHandlerAdapter;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 脚本方法代理
|
||||
*/
|
||||
public class ScriptMethodProxy {
|
||||
/**
|
||||
* 被代理的 bean
|
||||
*/
|
||||
private final Object bean;
|
||||
|
||||
/**
|
||||
* 原始的类
|
||||
*/
|
||||
private final Class<?> orignalClass;
|
||||
|
||||
private final List<Method> scriptMethods;
|
||||
|
||||
public ScriptMethodProxy(Object bean, Class<?> orignalClass, List<Method> scriptMethods) {
|
||||
this.bean = bean;
|
||||
this.orignalClass = orignalClass;
|
||||
this.scriptMethods = scriptMethods;
|
||||
}
|
||||
|
||||
public Object getProxyScriptMethod() {
|
||||
|
||||
try {
|
||||
return new ByteBuddy().subclass(orignalClass)
|
||||
.name(buildClassName()) // 设置生成的类名
|
||||
.method(ElementMatchers.any())
|
||||
.intercept(InvocationHandlerAdapter.of(new AopInvocationHandler(bean, scriptMethods)))
|
||||
.annotateType(orignalClass.getAnnotations())
|
||||
.make()
|
||||
.load(ScriptBeanProxy.class.getClassLoader())
|
||||
.getLoaded()
|
||||
.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new LiteFlowException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildClassName() {
|
||||
return StrUtil.format("{}.ByteBuddy${}",
|
||||
ClassUtil.getPackage(orignalClass),
|
||||
SerialsUtil.generateShortUUID());
|
||||
}
|
||||
|
||||
public static class AopInvocationHandler implements InvocationHandler {
|
||||
private final Object bean;
|
||||
|
||||
private final Class<?> clazz;
|
||||
|
||||
private final Set<Method> methodSet;
|
||||
|
||||
public AopInvocationHandler(Object bean, List<Method> methods) {
|
||||
this.bean = bean;
|
||||
this.clazz = LiteFlowProxyUtil.getUserClass(bean.getClass());
|
||||
this.methodSet = new HashSet<>(methods);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
Optional<Method> invokeMethodOp = Arrays.stream(clazz.getMethods())
|
||||
.filter(method::equals)
|
||||
.findFirst();
|
||||
|
||||
if (!invokeMethodOp.isPresent()) {
|
||||
String errorMsg = StrUtil.format("cannot find method[{}]", clazz.getName(), method.getName());
|
||||
throw new ScriptBeanMethodInvokeException(errorMsg);
|
||||
}
|
||||
|
||||
if (!methodSet.contains(method)) {
|
||||
String errorMsg = StrUtil.format("script method[{}.{}] cannot be executed", clazz.getName(), method.getName());
|
||||
throw new ScriptBeanMethodInvokeException(errorMsg);
|
||||
}
|
||||
|
||||
return invokeMethodOp.get().invoke(bean, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user