Как реализован AOP в Spring Framework?

«Как реализован AOP в Spring Framework?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Spring AOP — это прокси-ориентированная реализация аспектно-ориентированного программирования, построенная поверх IoC-контейнера. Она использует динамические прокси для применения аспектов к Spring-бинам.

Ключевые компоненты реализации:

  1. Прокси (Proxy): Spring создает прокси-объект для целевого бина. Все вызовы методов идут через этот прокси, который решает, нужно ли применять совет (Advice).
  2. Способы создания прокси:
    • JDK Dynamic Proxy: По умолчанию для бинов, реализующих хотя бы один интерфейс. Прокси реализует те же интерфейсы.
    • CGLIB Proxy: Используется, если бин не реализует интерфейсы (или задана настройка proxyTargetClass=true). Создает подкласс целевого класса.
  3. Аспект (@Aspect): Обычный Spring-бин, помеченный @Aspect, содержащий точки среза и советы.
  4. Совет (Advice): Метод, выполняемый в определенной точке. Аннотации: @Before, @After, @AfterReturning, @AfterThrowing, @Around.
  5. Точка среза (Pointcut): Выражение, определяющее, к каким методам (Join Points) применяется совет.

Пример:

@Aspect
@Component
public class LoggingAspect {
    // Определение Pointcut
    @Pointcut("execution(* com.example.service.*.*(..))")
    private void serviceLayer() {}
    // Advice, привязанный к Pointcut
    @Before("serviceLayer()")
    public void logMethodCall(JoinPoint jp) {
        System.out.println("Calling method: " + jp.getSignature().getName());
    }
}

Важное ограничение: Spring AOP работает только с публичными методами Spring-бинов, вызываемыми извне. Внутренние вызовы методов (this.method()) внутри бина не перехватываются. Для более сложных сценариев используется полный AspectJ с загрузкой во время компиляции (compile-time weaving).