方法参数注入如何在 Java 中工作

How does method parameter injection work in Java

背景: 在像 Spring 这样的几个 Java 框架中,有可能使用注入的参数值调用方法。一个很好的例子是 Spring Web/MVC 中的控制器操作,它接收 POST 值并具有重定向属性。

示例:

@RequestMapping(value = "/testform", method = RequestMethod.POST)
public ModelAndView testform(@RequestParam(value = "postvalue") String postvalue, RedirectAttributes attributes)
{
    if(postvalue.equals("Test"))
    {
        // Do stuff with attributes
    }
    return new ModelAndView("addresses");
}

例如,当我想在自己的应用程序中使用类似的东西时(不包含可用的 Spring)- 我最终得到了类似的东西(一起被黑了):

Strign actionname = "mymethod";
Controller controller = new SampleController();
for(Method method : controller.getClass().getDeclaredMethods())
{
    String name = method.getName();
    if(name.equals(actionname))
    {
        int parametercount = method.getParameterCount();
        if(parametercount == 0)  // No parameter
        {
            ModelAndView view = (ModelAndView) method.invoke(controller);
            // Do stuff
        }
        else if(parametercount == 1) // 1 String parameter
        {
            ModelAndView view = (ModelAndView) method.invoke(controller, new String("parameter1"));
            // Do stuff
        }
        else if(parametercount == 2) // 2 String parameters
        {
            ModelAndView view = (ModelAndView) method.invoke(controller, new String("parameter1"), new String("parameter2"));
            // Do stuff
        }
        else // Error
        {
            // Unsupported method
        }
        break;
    }
}

问题:此解决方案仅支持将字符串作为参数的 void、1 参数和 2 参数方法 - 无其他

问题:Java和Spring如何允许这样的功能? Spring 是否有适合最常用方法的大量 method.invoke(...) 或是否有更动态的解决方案来解决这个问题?

最终解决方案: 基于 Seelenvirtuose 的回答,我得到了这个(未完成的)解决方案:

else if(parametercount == 2)
{
    Object[] parameters = new Object[2];
    parameters[0] = new String("Hello");
    parameters[1] = new String("world!");
    method.invoke(controller, parameters);
}

除了任何一般的注入依赖框架(特别是Spring),您似乎在问如何反射调用具有任意数量参数的方法。

如您在 invoke method's signature 中所见,您在 数组 中提供了所有参数。所以你只需要 assemble 一个参数数组并提供:

Object[] arguments = createArguments(parametercount); // create array of correct size
(ModelAndView) method.invoke(controller, arguments);

请注意,varargs 被视为 arry。哦,请尊重关于字符串行为的评论。

原则上Spring做同样的事情,只是更复杂。

特别是他们不寻找名称(至少对于很多事情),而是寻找注释。可以获得类、方法、字段等注解

他们将使用的另一件事是 invoke 接受一个 vararg,它基本上是一个数组,因此他们没有为每个参数数量设置一个 if 分支,而是只传递一个具有正确数量元素的数组。