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
не срабатывает, следовательно, не печатает ценности.
В чем может быть причина этого?
Примечание:
-
Я тоже пытался сделать рабочих общественными классами, но это не сработало.
-
Также попытался изменить название методов, чтобы устранить любую проблему перегрузки, которая тоже не работала.
-
Пробовал различные другие точечные выражения, все напрасно, как сейчас.
-
В моем приложении есть и другие классы аспектов, работающие абсолютно нормально.
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) { // ... }
Источник: пружина АОП