Spring AOP - Point Cut не вызывается

У меня есть приложение SpringBoot. Я определил аннотацию «Track», и я аннотировал несколько методов в разных пакетах, которые я хочу рассмотреть. Аннотация была определена следующим образом:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Track {

}

Я не пропустил @EnableAspectJAutoProxy в классе @Configuration моего пакета.

У меня есть Pointcut и совет, определенные в аспекте, как показано ниже:

@Aspect
@Component
public class MyAspect {

@Pointcut("execution(@Track * *.*(..))")
void annotatedMethod() {
    // No Implementation required
}

@Around("annotatedMethod() && @annotation(methodLevelTrack)")
public void adviseAnnotatedMethods(ProceedingJoinPoint proceedingJoinPoint,
        Track methodLevelTrack) throws Throwable {

     // do some task
    proceedingJoinPoint.proceed();
    // do some task after the method is executed.
  }
}

Я намерен: для любого метода (помеченного @Track) в любом пакете, с любым модификатором доступа, любым количеством входных аргументов и любым типом возвращаемого значения следовать совету @Around аспекта.

Теперь интересная ситуация выглядит так: у меня есть класс «Engine», который вызывает другие классы и последующие системы для выполнения длительной операции. Определим класс следующим образом:

public class Engine {
  // bunch of other autowired objects

 public void processTask() {
   <autowired_object_A>.someMethod() // this method has been annotated with @Track
   <autowired_object_B>.someMethod() // this method has also been annotated with @ Track
   .... // bunch of other methods in other autowired objects that have been annotated with @ Track

   someMethodOfEngineClass(); // Now this has been defined in the Engine class as below, but pointcut doesn't recognize this method!

 }

 @Track
 private void someMethodOfEngineClass() {
  // do something
 }
}

Все методы "других" автоматически связанных объектов распознаются pointcut, как и ожидалось, но метод в этом классе Engine, помеченный @Track, не распознается. В чем загадка?

Я попытался сделать метод someMethodOfEngineClass общедоступным, вернуть что-то вместо void и всех этих комбинаций, но это не сработало.

Что мне не хватает? Это выражение определения pointcut? Я определил аспект в одном из подпакетов. Предполагается, что аспект должен быть определен на верхнем уровне в структуре пакета?

Не могли бы вы предложить что-нибудь, что может сработать? Я как бы застрял в этом.


person Partha    schedule 13.01.2018    source источник


Ответы (1)


Когда вы определяете aop, Spring создает прокси вокруг класса, поэтому, когда вызывается метод, фактически вызов делегируется прокси, например

your.package.Engine$$FastClassBySpringCGLIB$$c82923b4.someMethodOfEngineClass()

Но это работает только тогда, когда метод вызывается извне этого класса. Если вы вызываете метод класса из того же класса, вы фактически вызываете его this.someMethodOfEngineClass()

здесь -> http://www.nurkiewicz.com/2011/10/spring-pitfalls-proxying.html вы можете найти дополнительную информацию о проксировании.

поэтому прокси-сервер обходит и aop не работает.

person dawid    schedule 13.01.2018
comment
Хорошо, я попытался переместить someMethodOfEngineClass в другой класс, но представил этот метод как статический. АОП также не работает в этом случае. Является ли статичность кандидатом, не подходящим для проксирования? - person Partha; 14.01.2018
comment
Да, по статическому методу это не сработает. Это прокси-сервер Spring, поэтому Engine (метод, содержащий класс) необходимо ввести с помощью @Autowired, а затем получить к нему доступ. - person dawid; 14.01.2018