spring AoP, выражение pointcut для перегруженных методов с одинаковыми типами параметров

Я определил класс для операций CRUD с комментариями. Метод чтения перегружен.

class Comment{
    // method 1: returns all the comments by a user
    findAll(long userId, long subjectId, String param);

    // method 2: returns all the comments of all the users
    findAll(long subjectId, String param)
}

Выражение точечного среза, которое я пробовал, это

@Around("execution(* com.package..*Controller.findAll(..)) && args(userId,subjectId,..)")
public Object validateFindAll(final ProceedingJoinPoint proceedingJoinPoint, final long userId, final long subjectId) {
    // validate userId, if available
    // validate subjectId
}

Проблема: поскольку типы данных для userId и subjectId совпадают, точечное выражение при применении к методу 2 сдвигает значения параметров на 1 место. Это означает, что выражение не понимает, что первый параметр userId не передан. Вместо этого userId получает «subjectId» в качестве значения, а subjectId - в качестве значения соседнего параметра «param».

Примечание

  1. Я стараюсь не писать другой метод, например findUserComments ().

  2. Я хочу поддерживать согласованность во всем приложении. Есть и другие классы с похожими шаблонами операций CRUD.

Вопрос: можно ли определить выражение, применимое к обоим методам, если первый параметр userId является необязательным?

РЕДАКТИРОВАТЬ - Решение Пока я экспериментировал с различными подходами, предложенными в приведенных ниже решениях, я наконец удалил метод 2. Я обрабатываю этот случай в методе 1.


person Tushar Mishra    schedule 12.11.2014    source источник


Ответы (2)


Проблема на самом деле связана с перегрузкой метода. Поскольку вы передаете длинный идентификатор пользователя и длинный идентификатор субъекта, АОП всегда будет пытаться сопоставить эти аргументы. Решения могут быть

1) Создайте еще один pointcut для другого аргумента, то есть 1 для длинного, длинного и другого для длинного, String

2) Используйте сигнатуру переменного аргумента в начале, например

 @Around("execution(* com.org..findAll(..)) && args(..,subjectId,param)")
public Object validateFindAll(final ProceedingJoinPoint joinPoint, final long userId, final long subjectId) {

 }

вместо использования переменного аргумента в начале. Затем вы можете использовать метод getArgs () для определения аргументов. Это простое решение, но оно может замедлить вашу обработку.

3) Хотя в качестве дизайнерской проблемы я бы предложил инкапсулировать все ваши параметры в один объект и передать его. Вместо передачи нескольких параметров. Это поможет вам и в будущем.

person Bipul Sinha    schedule 12.11.2014

Вы не можете явно привязать параметр AspectJ, а затем ожидать, что он будет соответствовать несовместимой подписи. Таким образом, ваш pointcut будет соответствовать только findAll(long, long, ..), то есть «методу 1» в вашем примере. Вы можете указать необязательные аргументы с помощью .., но тогда вы не сможете привязать их к именованным параметрам.

Например, можно сопоставить оба метода и связать long subjectId и String param через args(.., subjectId, param), потому что оба параметра предсказуемо выровнены по правому краю в конце подписи. Если вам нужен какой-либо необязательный (и, следовательно, несвязанный) параметр, вам нужно использовать thisJoinPoint.getArgs():

@Around("execution(* com.package..*Controller.findAll(..)) && args(.., subjectId, param)")
public Object validateFindAll(
    final ProceedingJoinPoint thisJoinPoint,
    final long subjectId,
    final String param
) {
    if (thisJoinPoint.getArgs().length == 3)
        System.out.println(thisJoinPoint + " -> " + thisJoinPoint.getArgs()[0] + ", " + subjectId + ", " + param);
    else
        System.out.println(thisJoinPoint + " -> " + subjectId + ", " + param);
    // (...)
}

Но хотя getArgs() является динамическим, он, вероятно, медленнее, чем привязка параметров, поскольку использует отражение. Может быть, иметь два pointcut все-таки не так уж и плохо. Если ваш метод совета делает сложные вещи до / после proceed(), вы все равно можете разделить эти вещи на вспомогательные методы и вызывать их из обоих советов.

person kriegaex    schedule 12.11.2014
comment
Тогда почему бы тебе не принять мой ответ вместо другого? - person kriegaex; 20.11.2014