2015-11-30 2 views
2

Фон: В некоторых фреймворках Java, таких как Spring, есть возможность иметь методы, вызываемые с введенными значениями параметров. Хорошим примером является действие контроллера в Spring Web/MVC, которое получает значение POST и имеет атрибут перенаправления.Как работает инъекция параметров метода в Java

Пример:

@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 не включены доступны) - я в конечном итоге с чем-то вроде этого (Hacked вместе):

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; 
    } 
} 

Проблема: Это решение поддерживает только Пустоты, 1-параметров и 2-параметров методов, которые принимают строку в качестве аргумента - ничто иное

Вопрос: Как Java и Spring позволяют такую ​​функцию? Имеет ли весна огромный массив методов.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); 
} 
+3

Не используйте '==' для сравнения строк в Java. 'if (postvalue ==" Test ")' должно быть: 'if (postvalue.equals (" Test "))' – Jesper

+0

Кроме того, никогда не нужно использовать 'new String (...)' с литералом. Просто напишите '' parameter1 "' вместо 'new String (" parameter1 ")'. – Jesper

+0

Не используйте магию имени, используйте аннотации, например, Spring. Таким образом, вам не нужно полагаться на количество и порядок параметров, просто вызовите 'Method.getParameterAnnotations()' и используйте это, чтобы определить, что вводить в какой параметр. – biziclop

ответ

4

Помимо каких-либо рамок инъекции зависимостей в целом (и весной конкретно), вы, кажется, спросить, как рефлексивно вызывают методы с произвольным числом параметров.

Как вы можете видеть в invoke method's signature, вы предоставляете все параметры в массиве . Таким образом, вы просто должны собрать массив аргументов и предусматривают, что:

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

Обратите внимание, что переменной длины рассматриваются как Arry. О, и, пожалуйста, уважайте комментарии о строковых поведении.

+0

Спасибо, что решил мою проблему. Я всегда инициализировал массив непосредственно данными (во время объявления), но никогда не думал об установке значений позже и передавал массив объектов методу invoke. – swaechter

3

В принципе весна делает то же самое, только сложнее.

Особенно они не ищут имен (по крайней мере для многих вещей), а для аннотаций. Вы можете получить аннотации классов, методов, полей и т. Д.

Другое, что они будут использовать, это то, что invoke принимает vararg, который в основном представляет собой массив, поэтому вместо того, чтобы иметь одну ветвь для каждого числа параметров, они передают только массив с правильным количеством элементов.

+0

Действительно, но некоторые люди предпочитают параметр -paramaters, поэтому компилятор Java добавляет отладочную информацию, и вы можете получить имена параметров.Также vararg не является подходящим решением (операции с массивом для получения значений POST) – dasskorpion

Смежные вопросы