Что такое AOP (Aspect-Oriented Programming)?
4. Статические Pointcut → быстрее динамических 5. Избегайте состояния в аспектах (Singleton!) 6. @Around → не забудьте pjp.proceed()
🟢 Junior Level
AOP — способ добавить общую функциональность (логирование, транзакции) ко многим классам, не изменяя их код.
Простая аналогия: Представьте, что вы хотите записывать каждый звонок в компании. Вместо того чтобы просить каждого сотрудника вести журнал, вы ставите автоматическую запись всех звонков.
// Без AOP:
public void save() {
log.info("Начало"); // Повторяется везде
repository.save(entity);
log.info("Конец");
}
// С AOP:
@LogExecution // ← Одна аннотация!
public void save() {
repository.save(entity);
}
Зачем:
- Убирает дублирование кода
- Бизнес-логика отдельно, инфраструктура отдельно
- Легко включить/выключить
🟡 Middle Level
Spring AOP vs AspectJ
| Spring AOP | AspectJ | |
|---|---|---|
| Как | Прокси в рантайме | Изменение байт-кода |
| Что может | Только public методы | Методы, поля, конструкторы |
| Self-invocation | ❌ Не работает | ✅ Работает |
| Сложность | Простой | Сложный настройка |
Spring AOP работает только с Spring-бинами (вызовы через прокси). AspectJ работает с любыми объектами, т.к. внедряется на уровне байт-кода (compile-time или load-time weaving).
Термины AOP
Aspect (Аспект) = модуль сквозной логики
Pointcut (Точка) = где применять (выражение)
Advice (Совет) = что делать (логика)
Join Point (Точка соединения) = конкретный метод
Типы Advice
@Before // До метода
@After // После метода (всегда)
@AfterReturning // После успешного
@AfterThrowing // При исключении
@Around // Вместо метода (самый мощный)
Пример аспекта
@Aspect
@Component
public class LoggingAspect {
@Around("@annotation(LogExecution)")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
return pjp.proceed(); // Вызов оригинального метода
} finally {
long duration = System.currentTimeMillis() - start;
log.info("Выполнено за " + duration + "ms");
}
}
}
🔴 Senior Level
Interceptor Chain
Вызов метода → ReflectiveMethodInvocation:
1. SecurityInterceptor → проверка прав
2. TransactionInterceptor → транзакция
3. CacheInterceptor → кэш
4. LoggingAspect → логирование
5. Target method → ваш код
→ Каждый возвращает результат или бросает exception
→ Порядок определяется @Order
Производительность
Оверхед AOP:
→ Создание MethodInvocation объекта
→ Проход по списку интерцепторов
→ Рефлексия или прямой вызов
→ ~1-5 мкс на вызов
→ В Highload (1M RPS) → заметно!
Spring 6 + Virtual Threads
`synchronized` (ключевое слово) в аспектах → Pinning виртуальных потоков!
→ Проверьте, не блокируют ли ваши аспекты системные потоки
Production Experience
Полный пример с
Aroundбезproceed()— в файле [[16. Что такое аспект, advice, pointcut, join point]].
Best Practices
- Spring AOP → 95% случаев
- AspectJ → приватные методы, поля
- @Order → порядок аспектов
- Статические Pointcut → быстрее динамических
- Избегайте состояния в аспектах (Singleton!)
- @Around → не забудьте pjp.proceed()
Резюме для Senior
- AOP = сквозная функциональность без дублирования
- Spring AOP = прокси, AspectJ = байт-код
- Interceptor Chain → порядок через @Order
- Оверхед ~1-5 мкс на вызов
- Pinning → осторожно с synchronized в аспектах
- pjp.proceed() → обязательно в @Around
🎯 Шпаргалка для интервью
Обязательно знать:
- AOP = сквозная функциональность (логирование, транзакции, кэш) без дублирования кода
- Spring AOP работает через прокси в рантайме; AspectJ — через изменение байт-кода
- Ключевые термины: Aspect (модуль), Pointcut (где), Advice (что), Join Point (конкретный метод)
- 5 типов Advice: @Before, @After, @AfterReturning, @AfterThrowing, @Around
- @Around — самый мощный, но ОБЯЗААН вызывать pjp.proceed()
- Порядок аспектов определяется через @Order
- Spring AOP: только public методы Spring-бинов, self-invocation НЕ работает
- Оверхед AOP: ~1-5 мкс на вызов, в Highload суммируется
Частые уточняющие вопросы:
- Почему Spring AOP не работает с private-методами? → Прокси перехватывает только вызовы через proxy object, private-методы недоступны
- Когда выбрать AspectJ вместо Spring AOP? → Когда нужны private-методы, поля, конструкторы, или self-invocation
- @After vs @AfterReturning — в чём разница? → @After = всегда (как finally), @AfterReturning = только при успешном завершении
- Что такое ReflectiveMethodInvocation? → Pipeline Spring, последовательно проходящий все interceptors
Красные флаги (НЕ говорить):
- «Spring AOP работает с private-методами» — не работает
- «@Around без proceed() допустим» — метод не вызовется вообще
- «AOP добавляет миллисекунды overhead» — наносекунды (1-5 мкс)
- «Аспект хранит состояние в полях» — аспект = Singleton, не потокобезопасно
Связанные темы:
- [[13. Что такое прокси в Spring]]
- [[14. Когда Spring создаёт прокси]]
- [[16. Что такое аспект, advice, pointcut, join point]]
- [[17. Что делает аннотация @Transactional]]