gpt4 book ai didi

Java 将字符串变量作为回调函数传递

转载 作者:行者123 更新时间:2023-11-30 02:52:32 24 4
gpt4 key购买 nike

如何在回调中传递方法类变量?

我有以下代码:

PostsController postController = new PostsController();
router.get("/").handler(postController::index);

但是我的 Controller 将是动态的,我如何传递动态类及其函数。我尝试了以下代码

Class controller = Class.forName("some.package"+controllerName); //PostsController
Method[] methods = controller.getMethods();
//some loop
Method m = methods[i]; // This is the index method of my controller
router.get(somePath).handler(m); // How can I pass my method m as callback?

帖子 Controller

public class PostsController {

@Route(method="get", path = "/")
public void index(RoutingContext routingContext){
routingContext.response()
.putHeader("content-type", "application/json; charset=utf-8")
.end(Json.encodePrettily("{}"));
}

}

最佳答案

最干净的解决方案是使用 interface定义通用功能,例如

public interface Controller {
void index(RoutingContext routingContext);
}
public class PostsController implements Controller {
@Route(method="get", path = "/")
public void index(RoutingContext routingContext){
routingContext.response()
.putHeader("content-type", "application/json; charset=utf-8")
.end(Json.encodePrettily("{}"));
}
}

 

Class<? extends Controller> controllerType =
Class.forName("some.package"+controllers.getString(i))
.asSubclass(Controller.class);
Controller controller=controllerType.newInstance();
Handler<RoutingContext> h=controller::index;

当然,这不会与基于注释的处理交互。动态解决方案看起来像

Class<?> controllerType = Class.forName("some.package"+controllers.getString(i));
MethodHandles.Lookup lookup=MethodHandles.lookup();
Method[] methods = controllerType.getMethods();
Object instance = null;
for (Method m : methods) {
Route annotation = m.getAnnotation(Route.class);
if (annotation != null) {
if(instance == null) instance = controllerType.newInstance();
Handler<RoutingContext> handler
=createHandler(lookup, instance, m, RoutingContext.class);
router.get(annotation.path()).handler(handler);
}
}

 

static <T> Handler<T> createHandler(MethodHandles.Lookup lookup,
Object instance, Method m, Class<T> arg) throws Throwable {

MethodHandle mh=lookup.unreflect(m);
MethodType t=mh.type();
Class<?> receiver=t.parameterType(0);
if(t.parameterCount()!=2
|| !receiver.isAssignableFrom(instance.getClass())
|| !t.parameterType(1).isAssignableFrom(arg))
throw new IllegalArgumentException(m+" not suitable for Handler<"+arg.getName()+'>');
t=t.dropParameterTypes(0, 1);
return (Handler)LambdaMetafactory.metafactory(lookup, "accept",
MethodType.methodType(Handler.class, receiver),
t.changeParameterType(0, Object.class), mh, t)
.getTarget().invoke(instance);
}

这在关于您的 Handler 的某些假设下有效。您未指定的接口(interface)。如果它的定义如下:interface Handler<T> extends Consumer<T> {} ,它开箱即用。否则,你必须适应"accept"函数接口(interface)函数方法的实际名称。如果类型参数有限制,则必须更改 t.changeParameterType(0, Object.class)行使用实际绑定(bind)(类型删除后 Handler 的参数类型)。

通常,这需要非常小心,因为您不会立即收到错误反馈。在最坏的情况下,只有在实际调用回调时(使用某些参数)才会检测到错误。

原则上,您也可以创建一个封装方法反射调用的 lambda 表达式,即

Handler<RoutingContext> handler=rc -> { try {
m.invoke(capturedInstance, rc);
} catch(ReflectiveOperationException ex) { ex.printStackTrace(); }};

但这并不能改变这样一个事实:您只会很晚才检测到错误......

关于Java 将字符串变量作为回调函数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38198333/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com