1. Обзор
В этой статье мы обсудим различные типы рекомендаций АОП, которые могут быть созданы весной.
Консультации это действие, принятое аспектом в определенной точке присоединения. Различные типы советов включают в себя “вокруг”, “до” и “после” советы. Основная цель аспектов заключается в поддержке перекрестных проблем, таких как лесозаготовки, профилирование, кэширование и управление транзакцией.
И если вы хотите пойти глубже в pointcut выражения, проверить предыдущие интро к этим .
2. Включение консультаций
С Spring вы можете объявить советы, используя аннотации AspectJ, но сначала применять @EnableAspectJAutoProxy аннотация к классу конфигурации , что позволит поддерживать обработку компонентов, отмеченных системой @Aspect аннотация.
@Configuration @EnableAspectJAutoProxy public class AopConfiguration { ... }
2.1. Весенняя загрузка
В проектах Spring Boot мы не должны явно использовать @EnableAspectJAutoProxy . Есть специальная АопаутоКонфигурация что позволяет поддержку AOP весны, если Аспект или Консультации находится на классной симпатии.
3. Перед советом
Этот совет, как следует из названия, выполняется до точки присоединения. Это не предотвращает дальнейшее выполнение метода, который он советует, если исключение не брошено.
Рассмотрим следующий аспект, который просто регистрирует имя метода, прежде чем он называется:
@Component @Aspect public class LoggingAspect { private Logger logger = Logger.getLogger(LoggingAspect.class.getName()); @Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {}; @Before("repositoryMethods()") public void logMethodCall(JoinPoint jp) { String methodName = jp.getSignature().getName(); logger.info("Before " + methodName); } }
журналМетходКолл рекомендации будут выполнены до того, как какой-либо метод репозитория будет определен репозиторийМетоды pointcut.
4. После консультации
После консультации, объявленной с помощью @After аннотация, выполняется после выполнения метода, независимо от того, было ли брошено исключение.
В некотором смысле, это похоже на наконец блок. В случае, если вам нужен совет, который будет запущен только после нормального выполнения, вы должны использовать возвращаясь советы объявлено @AfterReturning аннотация. Если вы хотите, чтобы ваш совет был запущен только тогда, когда целевой метод бросает исключение, вы должны использовать бросали советы, объявлено с помощью @AfterThrowing аннотация.
Предположим, что мы хотим уведомить некоторые компоненты приложения при новом экземпляре Фу создается. Мы могли бы опубликовать событие из ФуДао , но это нарушило бы единый принцип ответственности.
Вместо этого мы можем достичь этого, определив следующий аспект:
@Component @Aspect public class PublishingAspect { private ApplicationEventPublisher eventPublisher; @Autowired public void setEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } @Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {} @Pointcut("execution(* *..create*(Long,..))") public void firstLongParamMethods() {} @Pointcut("repositoryMethods() && firstLongParamMethods()") public void entityCreationMethods() {} @AfterReturning(value = "entityCreationMethods()", returning = "entity") public void logMethodCall(JoinPoint jp, Object entity) throws Throwable { eventPublisher.publishEvent(new FooCreationEvent(entity)); } }
Обратите внимание, во-первых, что с помощью @AfterR eturning аннотация, которую мы можем получить доступ к значению возврата целевого метода. Во-вторых, объявив параметр типа Присоединиться кpoint, мы можем получить доступ к аргументам призыва целевого метода.
Далее мы создаем слушателя, который будет просто войти событие:
@Component public class FooCreationEventListener implements ApplicationListener{ private Logger logger = Logger.getLogger(getClass().getName()); @Override public void onApplicationEvent(FooCreationEvent event) { logger.info("Created foo instance: " + event.getSource().toString()); } }
5. Вокруг консультации
Вокруг консультации окружает точку присоединения, такую как вызов метода.
Это самый мощный совет. Вокруг советы могут выполнять пользовательское поведение как до, так и после вызова метода. Он также отвечает за выбор, следует ли перейти к точке соединения или сократить рекомендованное исполнение метода, предоставив свою собственную стоимость возврата или забросив исключение.
Чтобы продемонстрировать его использование, предположим, что мы хотим измерить время выполнения метода. Давайте создадим аспект для этого:
@Aspect @Component public class PerformanceAspect { private Logger logger = Logger.getLogger(getClass().getName()); @Pointcut("within(@org.springframework.stereotype.Repository *)") public void repositoryClassMethods() {}; @Around("repositoryClassMethods()") public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.nanoTime(); Object retval = pjp.proceed(); long end = System.nanoTime(); String methodName = pjp.getSignature().getName(); logger.info("Execution of " + methodName + " took " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms"); return retval; } }
Этот совет срабатывает, когда любой из точек присоединения соответствует репозиторийКлассМетоды pointcut выполняется.
Этот совет принимает один параметр типа ProceedingJointPoint . Параметр дает нам возможность принять меры до вызова целевого метода. Я n этот случай, мы просто сохранить время начала метода.
Во-вторых, тип возврата рекомендаций Объект так как целевой метод может вернуть результат любого типа. Если целевой метод пустота, нулевой будут возвращены. После вызова целевого метода мы можем измерить время, войти в него и вернуть значение результата метода вызывающему абоненту.
6. Обзор
В этой статье мы изучили различные типы советов весной и их декларации и реализации. Мы определили аспекты, используя схематизированный подход и используя аннотации AspectJ. Мы также предоставили несколько возможных консультаций приложений.
Реализация всех этих примеров и фрагментов кода можно найти в мой проект GitHub .