2016-11-18 9 views
2

Я использую АОП на основе XML весной, и у меня есть следующий Pointcut:Вокруг советов себя странно

<aop:aspect id=".." ref=".."> 
    <aop:pointcut id="interceptController" expression="execution(ModelAndView org.springframework.web.servlet.mvc.Controller+.handleRequest(HttpServletRequest, ..))" /> 
    <aop:around method="myAroundAdvice" pointcut-ref="interceptController" /> 
</aop:aspect> 

Мой совет заключается в следующем:

public Object myAroundAdvice(ProceedingJoinPoint jp) throws Throwable { 
    if (someCondition) { 
     Object test = jp.proceed(); 
     return test; 
    } 
    else { 
     return new ModelAndView("redirect:index.htm"); 
    } 
} 

Проблема с приведенным выше кодом заключается в том, что все работает нормально, если мы попадаем в истинное предложение выражения if, однако, если мы попадаем в предложение else, программа вылетает с ошибкой:

SEVERE: Servlet.service() for servlet ... threw exception 
java.lang.ClassCastException: org.springframework.web.servlet.ModelAndView cannot be cast to java.lang.Boolean 

Итак, я поставил точку останова на линии Object test = jp.proceed, и я заметил, что jp.proceed(); возвращает логический true. Следовательно, в предложении else, когда я возвращаю новый ModelAndView, он сбой, так как он ожидал, что логическое значение будет возвращено из совета.

Почему на земле есть логическое значение, которое ожидается от этого совета? В Pointcut выражении я уточнил, что возвращаемый тип исполнения метода я совпадающей ModelAndView, следовательно, proceed(), а также мой совет должен возвращать ModelAndView ..

Что я здесь отсутствует?


UPDATE: Как было отмечено, я попробовал напечатать joinpoint. Поэтому я напечатал joinpoint, а также его цель:

System.out.println("jp is : " + jp.toString()); 
System.out.println("target is : " + jp.getTarget().toString()); 

Это печатает следующее при посещении веб-страницы:

jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(preHandle) 
target is : [email protected] 

jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(postHandle) 
target is : [email protected] 

jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(afterCompletion) 
target is : [email protected] 

Обратите внимание, что LoginInterceptor расширяет HandlerInterceptorAdapter класс, так почему же соответствия с моим срезом точек ? Потому что HandlerInterceptorAdapter находится в servlet.handler, пока я матч на servlet.mvc.Controller+.handleRequest.


Целые stracktrace:

18-nov-2016 14:52:26 org.apache.catalina.core.StandardWrapperValve invoke 
SEVERE: Servlet.service() for servlet ... threw exception 
java.lang.ClassCastException: org.springframework.web.servlet.ModelAndView cannot be cast to java.lang.Boolean 
    at com.sun.proxy.$Proxy32.preHandle(Unknown Source) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:865) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:112) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:612) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503) 
    at java.lang.Thread.run(Thread.java:695) 
+0

Вы проверили, какой именно метод был перехвачен? И где именно происходит «ClassCastException»? –

+0

@PredragMaric Он соответствует методу 'handleRequest' контроллера (который является' AbstractController'). Следовательно, мой контроллер расширяет 'AbstractController' и реализует метод' handleRequestInternal'. Следовательно, я совпадаю с методом 'handleRequest', который вызовет мой метод' handleRequestInternal', если я вызову 'continue()', и еще я хочу вернуть новый 'ModelAndView', чтобы перенаправить пользователя. Что касается исключения, он бросается на 'return test;'. Я включу весь стек в мой пост. – HyperZ

ответ

1

Я думаю, что ваш не срез точек перехвата, что вы думаете, что он делает. По какой-то причине он, похоже, перехватывает методы, возвращающие логические значения. Попробуйте распечатать jp на консоли и посмотреть, какой метод вы перехватили.

pointcut как таковой выглядит в основном в порядке, но меня поражает одна вещь: ModelAndView - это не полное имя класса. Может быть, вы хотите это изменить.

+0

Вы правы, я напечатал 'jp.getTarget(). ToString()', который печатает некоторый класс 'LoginInterceptor' в моем проекте.Кажется, что он перехватывает метод 'preHandle' класса' LoginInterceptor', который действительно возвращает логическое значение. Однако этот класс 'LoginInterceptor' расширяет' org.springframework.web.servlet.handler.HandlerInterceptorAdapter', поэтому я не понимаю, почему этот метод перехвачен, так как мой pointcut должен только перехватывать 'HandleRequest' из' servlet.mvc. Controller + ', в то время как этот метод находится в' servlet.handler' ... Обратите внимание, что я изменил 'ModelAndView' на его полное имя. – HyperZ

+0

Я предполагаю, что есть другой pointcut, связанный с тем же методом консультаций, потому что тот, который вы показываете в своем вопросе, не будет перехватывать такие методы, как 'preHandle',' postHandle' или 'afterCompletion'. Пожалуйста, проверьте свой аспектный код, а также свою конфигурацию для других мест, ссылающихся на метод 'myAroundAdvice'. – kriegaex

+0

Правильно, это то, о чем я думал, однако, оригинальный проект не интегрировал АОП. Моя задача - объединить АОП, чтобы делать всевозможные вещи. Я прокомментировал все остальные точки, так что это действительно единственный pointcut, однако проблема сохраняется. Чтобы быть на 100% уверенным, я изменил имя совета, и в моем XML-файле упоминается это новое имя, однако, такое же поведение сохраняется, следовательно, я уверен, что нет другого pointcut, который случайно указывал на то же самое совет. Это действительно странно. Я тоже показал это своему преподавателю, и он тоже споткнулся. – HyperZ