Аспект вокруг совета не срабатывает на контроллере

У меня есть совет по аспектам, который отслеживает выполнение классов, аннотированных @Service. Код в настоящее время работает, но я хотел бы изменить его так, чтобы он отслеживал конечные точки REST на контроллерах вместо сервисов с автоматической связью Вот код:

@Aspect
public class AuditingAspect
{
    @Pointcut(
            //TODO Change pointcut from public methods in Services to REST endpoints in Controllers
            "execution(public * my.base.package..*.*(..))" //Must be in package
                    //+ " && @within(org.springframework.stereotype.Service)" //Has to be a service
                    + " && @within(org.springframework.stereotype.Controller)" //Has to be a controller
    )
    public void auditLoggingPointCut() {
        //no op
    }

    @Around(value ="auditLoggingPointCut()")
    public Object logAround(final ProceedingJoinPoint joinPoint) throws Throwable
    {
        System.out.println("Exection");

        returnVal = joinPoint.proceed();

        // Now Do The After Logging Part
        afterReturningLog(joinPoint, returnVal) ;

        return returnVal;
    }

    private void afterReturningLog(final JoinPoint joinPoint, final Object returnValue)
    {
        System.out.println("Exiting");
    }
}

Когда я изменяю "inside" с @Service на @Controller, я не вижу никаких выводов из совета, но метод выполняется при доступе из URL. Чем отличается контроллер, который будет игнорировать выполнение?

Класс Controller выглядит следующим образом:

@Controller
public class CaseReferralEndpoints {

    @Autowired
    CaseReferralFacade caseReferralFacade;

    @RequestMapping(value="/backgroundcheck/getcasereferrals", method = RequestMethod.GET)
    @ResponseBody
    public List<CaseReferralSection> getCaseReferrals(@RequestParam("caseID") Long caseID) {
        return caseReferralFacade.getCaseReferrals(caseID); 
    }
}

Вот мое приложение Context-aop.xml. Полная конфигурация намного больше, но я считаю, что это наиболее актуально.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd">



    <bean class="gov.dhs.uscis.elis2.backend.services.logging.AuditingAspect"/>

    <aop:aspectj-autoproxy proxy-target-class="false" />


</beans>

4 ответа

Предположим, что ваша конфигурация @within верна, потенциальное решение ваших проблем будет следующим:

<aop:aspectj-autoproxy proxy-target-class="true" />

Также вам нужно будет добавить CGLIB в ваш classpath

Вышеуказанные шаги необходимы, так как ваш контроллер не реализует интерфейс

Наконец, если у вас есть корневой контекст и веб-контекст, то относящиеся к AOP вещи должны быть применены к веб-контексту (наличие его в корневом контексте не будет работать для контроллеров, настроенных в веб-контексте)

ОБНОВИТЬ

В Gradle для добавления CGLIB в путь к классам добавьте:

'cglib:cglib:2.2.2'

В Maven это будет:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

Обнаружена ошибка внутри applicationContext.xml

Мои контроллеры были отфильтрованы от контекстного сканирования! Я один из многих разработчиков проекта, поэтому я не думал, что искать здесь изначально.

<context:component-scan>
    <!-- a bunch of packages -->

    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

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

Как ваше выражение pointcut имеет

 @within(org.springframework.stereotype.Service)

с символом && совет будет применяться только в вашем пакете до услуги.

и я надеюсь, что ваш класс контроллера не внутри ..Сервисный пакет, он может быть внутри.*.* Пакет контроллера, поэтому он не выполняется для контроллера

решение Удалить изнутри точки срез выражения

или добавить контроллер также внутри выражения среза точки

Предполагая, что ваш pointcut правильный, и вы используете два пружинных контекста, один для services/daos (appcontext) и один для контроллеров (servletcontext), мой совет идет в направлении неверной конфигурации.

Конфигурация AOP является одним из пружинных компонентов, которые применяются ТОЛЬКО в контексте, который объявлен / отсканирован.

Итак, если у вас есть servletcontext.xml для ваших контроллеров, ваши pointcut не будут применены, если вы не объявите конфигурацию контекста aop в этом контексте.

(Объявление контекста приложения понадобится, если вы хотите применить pointcuts к вашим службам.)

Другие вопросы по тегам