Я понимаю, что Spring AOP очень ограничен в своих возможностях (он может разрезать только открытые методы классов, которые являются бобами Spring, и только тогда, когда эти методы вызываются извне класса).Но теперь я обнаружил еще одно ограничивающее ограничение, когда задействованы интерфейсы.
Обычно, если класс находится в подклассах, у Spring AOP нет проблем с разрезанием всех их методов (даже переопределенных):
public class A {
public void methodA() { } //OK, can cut in
}
public class B extends A {
@Override
public void methodA() { } //OK, can cut in
public void methodB() { } //OK, can cut in
}
Но когда мы добавляем интерфейс в микшер, для Spring AOP все становится очень плохо:
public interface I {
public void methodA();
}
public class A implements I {
@Override
public void methodA() { } //OK, can cut in
public void methodB() { } //Fail, cannot see or cut into this method
}
public class B extends A {
@Override
public void methodA() { } //Fail, cannot see or cut into this method
public void methodC() { } //Fail, cannot see or cut into this method
}
Прежде всего, Spring AOP может разрезать только методы, которые есть в интерфейсе, и все остальное.- он не может видеть.Во-вторых, он может врезаться только в метод, который непосредственно реализует метод интерфейса - A.methodA()
.Он не может быть разрезан на тот же метод, переопределенный с помощью B.
Я использую универсальное выражение pointcut "execution(* method*(..))"
, чтобы разрезать все возможные методы, поэтому это не проблема с выражением.
Есть ли какие-либообойти это ограничение?Или я должен просто забыть о Spring AOP и использовать другой подход?
ОБНОВЛЕНИЕ: Хорошо, я нашел реальную причину проблемы.Я на самом деле полагался на плагин Intellij IDEA AOP, чтобы проверить это.Предполагается связать pointcut со всеми задействованными методами.Но он использовал «старую», динамическую JDK-прокси-стратегию вместо новой CGLIB-стратегии.Так что это не связывало его со всеми методами, но когда я фактически запустил свою программу, она правильно обрезала все методы.
Я использую Spring Boot 2, который использует «новую» стратегию CGLIB.Но на SB1 он все еще может использовать «старую» динамическую стратегию JDK-прокси, поэтому он все еще может там не работать.