Какие ключевые компоненты нужны для создания аспекта в Spring
Что проверяют
Понимаете ли вы, как Spring AOP устроен внутри: через прокси, а не через переписывание байткода. Следом почти всегда спрашивают, почему аспект не срабатывает при вызове метода из того же класса.
Как отвечать
Минимальный набор для работающего аспекта:
- зависимость:
aspectjweaverна classpath. В Spring Boot его подтягивает стартер для AOP, и автоконфигурация сама включает автопроксирование; в обычном Spring нужна@EnableAspectJAutoProxyна конфигурации; - класс-аспект:
@Aspectплюс@Componentили регистрация через@Bean. Одна@Aspectбин не создаёт, и аспект молча не работает; - pointcut: выражение, какие методы перехватывать. Чаще всего
execution(* com.app.service..*.*(..)),@annotation(com.app.Audited)для методов со своей аннотацией,within(...)для пакета. Выносится в метод с@Pointcutдля переиспользования; - advice: что делать и когда.
@Before,@AfterReturningс доступом к результату,@AfterThrowing,@After(срабатывает какfinally) и@Around, который получаетProceedingJoinPointи сам решает, вызывать лиproceed(); - join point: в Spring AOP это только выполнение метода бина. Через
JoinPointдоступны аргументы и сигнатура.
Порядок нескольких аспектов задаётся @Order. Типичные задачи: логирование, метрики, аудит, проверка прав; @Transactional и @Cacheable построены на том же прокси-механизме.
Weaving в Spring AOP происходит во время выполнения: контейнер оборачивает бин в прокси JDK (для интерфейсов) или CGLIB, в Spring Boot по умолчанию CGLIB. Weaving на этапе компиляции или загрузки классов это уже полноценный AspectJ.
Где спотыкаются
Не знают про self-invocation: вызов this.method() внутри бина идёт мимо прокси, и advice не выполняется. То же с private и final методами.
Забывают @Component на аспекте и долго ищут ошибку в выражении pointcut.
В @Around не вызывают proceed() или не возвращают его результат. Целевой метод тогда не выполняется или вызывающий получает null.