Подтвердить что ты не робот

Методы сопоставления точек с аннотированными параметрами

Мне нужно создать аспект с pointcut, соответствующий методу, если:

  • Является общедоступным
  • Его класс аннотируется с помощью @Controller (в конце концов не)
  • Один из его параметров (может иметь много) аннотируется с помощью @MyParamAnnotation.

Я думаю, что первые два условия легки, но я не знаю, можно ли выполнить третий с помощью Spring. Если это не так, возможно, я могу изменить его на:

  • Один из его параметров - это экземпляр типа com.me.MyType(или реализует некоторый интерфейс)

Считаете ли вы возможным достичь этого? И будет ли производительность хорошей?

Спасибо

EDIT. Один пример метода сопоставления. Как вы можете видеть, MyMethod не аннотируется (но может быть).

@Controller
public class MyClass {
    public void MyMethod (String arg0, @MyParamAnnotation Object arg1, Long arg3) {
        ...
    }
}

EDIT. Решение, которое я, наконец, использовал на основе ответов @Espen. Как вы можете видеть, я немного изменил условия: класс фактически не должен быть @Controller.

@Around("execution(public * * (.., @SessionInject (*), ..))")
public void methodAround(JoinPoint joinPoint) throws Exception {
    ...
}
4b9b3361

Ответ 1

Это была интересная проблема, поэтому я создал небольшое примерное приложение для решения дела! (И улучшил его с обратной связью Sinuhe.)

Я создал класс DemoController, который должен работать в качестве примера для аспект:

@Controller
public class DemoController {

    public void soSomething(String s, @MyParamAnnotation Double d, Integer i) {
    }

    public void doSomething(String s, long l, @MyParamAnnotation int i) {
    }

    public void doSomething(@MyParamAnnotation String s) {
    }

    public void doSomething(long l) {
    }
}

Аспект, который добавит точку соединения для первых трех методов, но не последний метод, где параметр не аннотируется с помощью @MyParamAnnotation:

@Aspect
public class ParameterAspect {

    @Pointcut("within(@org.springframework.stereotype.Controller *)")
    public void beanAnnotatedWithAtController() {
    }

    @Pointcut("execution(public * *(.., @aspects.MyParamAnnotation (*), ..))")
    public void methodWithAnnotationOnAtLeastOneParameter() {
    }

    @Before("beanAnnotatedWithAtController() " 
            + "&& methodWithAnnotationOnAtLeastOneParameter()")
    public void beforeMethod() {    
        System.out.println("At least one of the parameters are " 
                  + "annotated with @MyParamAnnotation");
    }
}

Первый pointcut создаст точку соединения для всех методов внутри классов, помеченных @Controller.

Второй pointcut добавит точку соединения, если будут выполнены следующие условия:

  • открытый метод
  • first * является подстановочным знаком для каждого типа возврата.
  • second * является подстановочным знаком для всех методов во всех классах.
  • (.., соответствует нулю для многих параметров любого типа перед аннотированным параметром.
  • @aspects.MyParamAnnotation (*), соответствует параметру, аннотированному с данной аннотацией.
  • ..) соответствует нулю для многих параметров любого типа после аннотированного параметра.

Наконец, совет @Before рекомендует все методы, в которых выполняются все условия в обеих точках.

Pointcut работает как с AspectJ, так и с Spring AOP!

Когда дело доходит до производительности. Накладные расходы небольшие, особенно с AspectJ, который выполняет переплетение во время компиляции или времени загрузки.