Я работаю с:
Spring Framework
4.3.3AspectJ
1.8.9
У меня есть следующий нормальный процесс:
@Controller
->@Service
->@Repository
У меня есть следующая пара о AOP
:
PersonaServicePointcut
PersonaServiceAspect
Сценарий следующий:
Класс @Service
имеет несколько методов, таких как: delete
, save
, update
и findOneById
. Они объявляются вместе в одном классе.
Для таких методов, как delete
и с update
по AOP
, я использую совет @Before
или @Around
для вызова метода findOneById
.
Причина в том, что не имеет смысла выполнять методы delete
или update
(рассмотрите сценарий Rest), если сущность не существует. Поэтому через это advice
должно быть выброшено исключение, скажем, исключение A, оно должно быть обработано в @ControllerAdvice
Практически такой же подход был применен для метода save
. Поэтому перед выполнением метода save
выполняется другой совет @Before
или @Around
, снова вызывая метод findOneById
. Если объект уже существует, должно быть выдано исключение, скажем, исключение B, оно должно быть обработано в @ControllerAdvice
Обратите внимание, что у меня есть 3 пункта/3 совета, которые используют метод findOneById
. Это проверить, существует ли сущность или нет.
Например:
@Pointcut(value=
"execution(* mypackage.PersonaServiceImpl.saveOne(otherpackage.Persona))
&& args(persona)")
public void saveOnePointcut(Persona persona){}
@Pointcut(value=
"execution(*
mypackage.PersonaServiceImpl.updateOne(otherpackage.Persona))
&& args(persona)")
public void updateOnePointcut(Persona persona){}
@Pointcut(value="execution(*
mypackage.PersonaServiceImpl.deleteOne(String)) && args(id)")
public void deleteOnePointcut(String id){}
Еще раз: эти 3 совета используют или выполняют метод findOneById
.
Проблема в том, что я добавляю новый pointcut, например:
@Pointcut(value="execution(*
mypackage.PersonaServiceImpl.findOneById(String))
&& args(id)")
public void findOneByIdPointcut(String id){}
Я создал этот pointcut, чтобы проверить, существует ли объект уже или нет, если он не существует, он должен выдать исключение типа C
(это для классического 404).
Кажется излишним выполнять метод findOneById
через совет @Before
или @Around
для самого метода findOneById
. Но мне это нужно для целей logging
и audit
, а также для создания исключения типа C. Это должно быть обработано каким-то @ControllerAdvice
Проблема заключается в том, что когда другие советы для методов delete/update/save
выполняются (помните, что они также вызывают и выполняют метод findOneById
), мой findOneByIdPointcut
выполняется без необходимости .
Мне нужно изменить объявление pointcut, чтобы указать что-то вроде этого:
@Pointcut(Alpha)
public void findOneByIdPointcut(String id){}
Где Alpha
:
выполнить совет до/вокруг для метода findOneById
@Service
, но никогда, если его вызов был выполнен из других советов из классаPersonaServiceAspect
.
Я пробовал много способов с комбинациями !execution
и !within
, но безрезультатно.
Даже когда я создал только один Pointcut, который перехватывает все методы @Service
с соответствующим уникальным советом @Around
, и через параметр ProceedingJoinPoint proceedingJoinPoint
я могу проверить, какой метод был вызван, а затем выполнить соответствующие элементы управления. Но опять такое поведение происходит.
Это означает, через следующее:
@Around("PersonaServicePointcut.anyMethodPointcut()")
public Object aroundAdviceAnyMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
где anyMethodPointcut
равно execution(* mypackage.PersonaServiceImpl.*(..))
Возможен ли такой подход? Как?
Спасибо.