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, который вы используете, обертывает целевые классы в прокси-классах, которые теряют свою аннотацию или исходная аннотация падает после плетения.

Я уверен, что есть лучший ответ, и я буду расширяться на своем, поскольку я думаю о более четком способе представить его.