Spring 3 MVC @Controller с перехватчиками AOP?
Кто-нибудь знает, почему, по-видимому, невозможно использовать AOP с аннотированными MVC-контроллерами? (см. Сообщение).
У меня есть @Controller, который перестает работать, как только я добавляю pointcut к нему.
Проблема заключается не в том, что перехватчик не вызывается, а в @Controller просто перестает работать (в журнале вы можете видеть, что вместо "Mapped URL path [/xx]] на обработчике" Yyy "вы получаете" нет URL-адреса "пути идентифицированы" ).
Я знаю, что есть механизм для добавления перехватчиков к контроллерам через handlerMapping, но мой вопрос специфичен для перехватчиков AOP. Не являются ли аннотированные контроллеры просто pojos в контейнере Spring как любое другое pojo? В чем разница? Почему?
@Controller
@RequestMapping("/user")
public class RestTestImpl implements RestTest {
@RequestMapping(value="/", method={RequestMethod.GET})
public @ResponseBody String deleteUsers(String arg) {
return "Xxxxx";
}
}
В моем сервлет-контексте я:
<context:component-scan base-package="org.xxx.yyy"></context:component-scan>
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
. . .
</bean>
И все работает просто отлично.
Но когда я добавляю:
<aop:config>
<aop:pointcut expression="execution(* org.xxx.*(..))" id="pc1"/>
<aop:advisor advice-ref="hibernateInterceptor" pointcut-ref="pc1" order="2" />
</aop:config>
Контроллер перестает быть контроллером (нет ошибок, просто он перестает связываться с указанным URL-адресом)!
Ответы
Ответ 1
Из Spring Ссылка MVC:
Примечание
При использовании интерфейсов контроллера (например, для проксирования AOP) убедитесь, что последовательно поместите все свои аннотации отображения - такие как @RequestMapping
и @SessionAttributes
- на интерфейсе контроллера, а не на классе реализации.
Конечно, эта заметка хорошо скрыта: -)
Ответ 2
Я столкнулся с той же проблемой и выяснил решение.
В действительности ваш контроллер (аннотированный @Controller) и ваши аспекты (аннотированные @Aspect) должны быть в одном и том же контексте Spring.
Обычно люди определяют свои контроллеры в dispatch-servlet.xml или xxx-servlet.xml и их службе beans (включая аспекты) в главном applicationContext.xml. Это не сработает.
Когда Spring инициализирует контекст MVC, он создаст прокси для вашего контроллера, но если ваши аспекты не в одном контексте, Spring не создаст для них перехватчики.
Вышеуказанный ssertion не зависит от
- в том, как вы объявляете свои контроллеры/аспекты (с помощью объявления XML или стиля аннотации)
- в выбранном вами стиле прокси (прокси JDK или CGLIB)
Я тестировал все комбинации, и все они работают до тех пор, пока контроллер и аспекты находятся в одном и том же контексте Spring
Ответ 3
Мое лучшее предположение, не делая серьезного копания, состоит в том, что механизм Spring AOP, который вы используете, обертывает целевые классы в прокси-классах, которые теряют свою аннотацию или исходная аннотация падает после плетения.
Я уверен, что есть лучший ответ, и я буду расширяться на своем, поскольку я думаю о более четком способе представить его.