Внутренняя работа аннотации @RequestParam Спрингса - PullRequest
6 голосов
/ 31 июля 2011

В Spring два следующих утверждения, если я не ошибаюсь, идентичны:

@RequestParam("type") String type
@RequestParam String type

Как Spring может узнать имя переменной 'type' (вторая версия).У меня сложилось впечатление, что эта информация была удалена из файлов классов, если она не была скомпилирована с флагом -g (включая отладочную информацию).

1 Ответ

6 голосов
/ 31 июля 2011

Короче говоря, это то, что имена параметров, по-видимому, компилируются, в противном случае вы получили бы исключение, указывающее, что Spring MVC не может определить имя параметра. То есть имена параметров не всегда сохраняются в байт-коде, но, похоже, если они есть, Spring их найдет, если нет, вам нужно указать их при добавлении аннотации @RequestParam.

Другие подробности доступны по этому подобному вопросу , и это ответов .


В 3.0.5.RELEASE эти аннотации обрабатываются в HandlerMethodInvoker.resolveHandlerArguments и, как представляется, если значение не указано, Spring использует RequestParam.value(). Это может вернуть пустую строку.

Далее, Spring использует HandlerMethodInvoker.resolveRequestParam, и там, где имя параметра пусто, он вызывает HandlerMethodINvoker.getRequiredParameterName с MethodParameter methodParam в качестве аргумента:

718     private String getRequiredParameterName(MethodParameter methodParam) {
719     String name = methodParam.getParameterName();
720     if (name == null) {
721         throw new IllegalStateException(
722                 "No parameter name specified for argument of type [" + methodParam.getParameterType().getName() +
723                         "], and no parameter name information found in class file either.");
724     }
725     return name;
726 }

Обратите внимание, что здесь он пытается извлечь информацию из methodParam, которая, если мы создадим резервную копию дерева, мы увидим, что resolveHandlerArguments фактически создает новый MethodParameter для каждого аргумента, который он процессы. Внутри MethodParameter мы можем взглянуть на getParameterName():

276 public String getParameterName() {
277     if (this.parameterNameDiscoverer != null) {
278         String[] parameterNames = (this.method != null ?
279                 this.parameterNameDiscoverer.getParameterNames(this.method) :
280                 this.parameterNameDiscoverer.getParameterNames(this.constructor));
281         if (parameterNames != null) {
282             this.parameterName = parameterNames[this.parameterIndex];
283         }
284         this.parameterNameDiscoverer = null;
285     }
286     return this.parameterName;
287 }

Так что здесь используется нечто, называемое ParameterNameDiscoverer, но это интерфейс, и моя трассировка не показывает, какую реализацию он использует, есть несколько . Глядя на LocalVariableTableParameterNameDiscoverer.getParameterNames , мы в конечном итоге вызываем LocalVariableTableParameterNameDiscoverer.ParameterNameDiscoveringVisitor как часть org.objectweb.asm.ClassReader, который, насколько я могу судить, пытается прочитать имя параметра вне байт-кода.

...