Spring-AOP pointcut не работает?


Ниже приведен мой фрагмент кода:

ServiceImpl.java

@Service
public class ServiceImpl implements Service {
  private Response worker(Audit send) throws ArgumentException {
    System.out.println("STEP_1");
    worker(send.getRequest(), send.getId());
  }

  private Response worker(Request request, String id) throws ArgumentException {
    System.out.println("STEP_2");
    try {
      //throwing some exception
    } catch (Exception e) {
      System.out.println("STEP_3");
    }
  }
}
Теперь я хочу, чтобы всякий раз, когда NullPointerException выбрасывается из метода worker(Request request, String id), как показано выше, я хотел бы выполнить какую-то конкретную задачу. Для этого я написал класс аспектов, который выглядит следующим образом:

Мой интеллект.java

@Aspect
@Component
public class MyAspect{
  @Pointcut("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
  private void someOperation(Request request) {}

  @Before("someOperation(request)")
  public void process(Request request) {
    System.out.println("SUCCESS");
  }

  @AfterThrowing("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
  public void doRecoveryActions() {
    System.out.println("EXCEPTION_SUCCESS");
  }
}

Выходной Ток:

STEP_1 
STEP_2
STEP_3

Желаемый Результат:

STEP_1 
STEP_2
STEP_3
SUCCESS
EXCEPTION_SUCCESS

Как вы можете видеть MyAspect.java не срабатывает, следовательно, не печатает ценности. В чем может быть причина этого?

Примечание:

  1. Я тоже пытался сделать рабочих общественными классами, но это не сработало.

  2. Также попытался изменить название методов, чтобы устранить любую проблему перегрузки, которая тоже не работала.

  3. Пробовал различные другие точечные выражения, все напрасно, как сейчас.

  4. В моем приложении есть и другие классы аспектов, работающие абсолютно нормально.

2 3

2 ответа:

Вы допустили типичную ошибку новичка Spring AOP: вы предполагаете, что он работает для частных методов, но, как ясно сказано в документации, это не так. Spring AOP основан на динамических прокси, и они работают только для открытых методов при реализации интерфейсов через прокси JDK и дополнительно для защищенных и пакетных методов при использовании прокси CGLIB.

Вы должны сделать метод worker() открытым, если вы хотите перехватить его с аспекта.

P.S.: полноценный аспект также работает для частных методов, но переход на другую структуру AOP был бы излишним здесь.


Update: у вас также есть другие проблемы в коде:

    Первый метод worker, даже если вы сделаете его общедоступным, ничего не вернет. Последнее утверждение должно быть return worker(send.getRequest(), send.getId());, а не просто worker(send.getRequest(), send.getId());.
  • ваш pointcut com.xyz.myapp.ServiceImpl.worker() никогда не будет совпадать, потому что у него есть пустой список аргументов, но у вашего метода есть аргументы. args() здесь вам не поможет.
  • в синтаксис вашего pointcut также неверен, потому что он не указывает тип возвращаемого значения для метода, даже *. Кроме того, само имя метода недостаточно, оно должно быть заключено в фактический тип pointcut, такой как execution(). То есть вы хотите написать что-то вроде:
@Pointcut("execution(* com.xyz.myapp.ServiceImpl.worker(..)) && args(request, ..)")
private void someOperation(Request request) {}

Для перехвата метода, создающего исключение, можно использовать следующий код (работает только в том случае, если методы являются открытыми):

 @AfterThrowing(pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",throwing="ex")
         public void doRecoveryActions(NullPointerException ex) {
          // ...
         }

Источник: пружина АОП