Spring AOP - ошибка AspectJ: неоднозначная привязка сеанса параметра (ов) через '||' в pointcut - PullRequest
2 голосов
/ 14 декабря 2011

Эта ошибка появляется при запуске пакета mvn из командной строки или из eclipse.

Странно то, что если я запускаю пакет mvn 3–4 раза, то ошибка больше не отображается и сборка завершена успешно! Также в eclipse есть красный 'x' в файле, где определен pointcut (в проводнике пакетов), но при открытии файла ошибки не возникает. Точки. Две точки, где '||' используется:

@Pointcut("((execution(gr.diassa.dslibweb.data.dto.GenericGrid gr.diassa.dslibweb.controller.*.*(..)) && args(session,..)) || (execution(gr.diassa.dslibweb.data.dto.GenericGrid gr.diassa.dslibweb.controller.*.*(..)) && args(..,session))) && excludeInitControllerMethods()")
public void controllerActionForMethodsThatReturnJsonString(HttpSession session) {

}

@Pointcut("((execution(org.springframework.web.servlet.ModelAndView gr.diassa.dslibweb.controller.*.*(..)) && args(session,..)) || (execution(org.springframework.web.servlet.ModelAndView gr.diassa.dslibweb.controller.*.*(..)) && args(..,session))) && excludeInitControllerMethods()")
public void controllerActionForMethodsThatReturnModelAndView(HttpSession session) {

}

Ничего подобного я не нашел нигде, кто-нибудь сталкивался с этим раньше?

1 Ответ

4 голосов
/ 10 декабря 2014

Это допустимая проблема, указанная компилятором, но также и недостаток AspectJ из практического POV.

Обратите внимание: вы используете не только pointcut для привязки совета,но в то же время вы пытаетесь подобрать какое-либо значение параметра из соответствующей точки.Теперь проблема в том, что вы определяете два альтернативных сценария (с ||) - к сожалению, может случиться, что оба сценария могут произойти.Это не будет проблемой для сопоставления и определения совета.Но так как вы хотите выбрать значение параметра, AspectJ не знает, что делать, когда обе ветви верны.

В вашем примере может быть методомкоторый принимает два разных session параметра в начале и конце списка параметров.Такой метод будет соответствовать обеим альтернативным ветвям pointcut.Какую сессию AspectJ должен вернуть в этом случае ??

Хотя все это логически вменяемое и правильное, с практической точки зрения это часто оказывается недостатком.

  • Обычно - и довольно часто, когда вы начинаете писать такие точки - вы просто знаете, что конкретный объект, который вы хотите, всегда один и тот же, или, по крайней мере, различия не имеют значения.Или вы предполагаете, что вы получаете совпадение из первой применимой ветви («оценка короткого замыкания») и вам не нужны дальнейшие совпадения
  • во всех случаях, в которые я попадал, AspectJ был неспособен выяснить, что две ветви не пересекаются, даже в тех случаях, когда это может быть получено статически.
  • см. Также эту ошибку https://bugs.eclipse.org/bugs/show_bug.cgi?id=121805 (сообщается в 2005 году, вновь открыто в 2014 году).Похоже, что реализовать эту штуку сложно и сложно понять правильно.Эта ошибка также может быть объяснением того, почему эта проблема не обнаруживается последовательно (как и должно быть)

Таким образом, единственное средство - это разделить ваш pointcut на отдельный pointcut для каждой ветви и написать отдельныйсовет для каждой отрасли .Обычно вы хотите делегировать общий метод реализации из всех этих советов.Уродливо, но на практике решает эту проблему

...