Spring AOP

Aspect – модуль, который определяет Advices, срезы и привязки. Это кросс-функциональные заботы, такие как логирование, аудит, безопасность и т. д.

Join Point – точка в программе, такая как выполнение метода, где можно применить Advices (advice). В Spring AOP, join points представляют собой выполнение методов.

Advice – действие, предпринимаемое аспектом в определенной точке соединения. Существуют разные типы Advices, такие как before, after, after-returning, after-throwing, и around.

Pointcut – выражение, которое выбирает определенные join points. Advices применяются к join points, выбранным через pointcuts

Target – объект, к которому применяется Advices.

Proxy – объект, созданный после применения Advicesа к целевому объекту.

Weaving – процесс комбинирования аспектов с другим типом приложения для создания прокси-объекта. Это может быть выполнено во время компиляции (CTW), загрузки класса (LTW) или во время выполнения. Introduction (Inter-type declaration) – добавление новых методов или свойств в существующие классы.

Транзакция – последовательность действий, которые либо полностью выполняются, либо полностью отменяются.

ACID – принципы транзакций — Атомарность, Согласованность, Изоляция и Долговечность (Atomicity, Consistency, Isolation, Durability).

Propagation – определяет, как транзакции относятся к друг другу. Например, REQUIRED, REQUIRES_NEW, SUPPORTS и т. д.

Isolation – уровень изоляции транзакции определяет, как данные, доступные одной транзакции, становятся видимыми для других.

@Transactional – аннотация Spring для объявления транзакционного метода.

Transaction Manager – компонент, который управляет транзакциями. Например, DataSourceTransactionManager для JDBC.

Rollback – отмена изменений, выполненных в рамках транзакции. 


Spring AOP 

AOP это сокращение от Aspect-Oriented Programming

В первую очередь, Spring AOP помогает разработчикам писать более чистый и модульный код. Вы можете сосредоточиться на основной логике вашего приложения, не беспокоясь о дополнительных функциях, таких как логирование или безопасность. Эти “перекрестные” задачи (cross-cutting concerns) легко управляются с помощью аспектов в AOP

Представьте, что у вас есть дом. В этом доме есть разные комнаты: кухня, спальня, гостиная и так далее. Теперь представьте, что вы решаете установить в доме систему безопасности. В каждой комнате вы ставите датчик движения. Но ведь датчик движения — это не основная часть комнаты, верно? Он просто добавляется для выполнения какой-то дополнительной функции. 

В этом примере каждая комната — это какой-то отдельный модуль вашего приложения. А система безопасности, которую вы решили добавить — это пример функции, которую вы хотите “вплести” в разные части вашего приложения, не меняя их основного кода. Именно это и позволяет сделать AOP! 


Аспекты в Spring AOP

Аспект в Spring AOP — это модуль, который определяет “перекрестные” или “сквозные” задачи, такие как логирование, безопасность или транзакции. Эти задачи обычно затрагивают многие части приложения и не связаны напрямую с бизнес-логикой. 

Как аспекты работают?

Аспекты работают таким образом, что они “внедряются” или “вплетаются” в ваш код в определенные места, которые вы указываете. Это похоже на то, как вы можете настроить датчики движения в разных комнатах вашего дома. Когда происходит какое-то событие (например, движение в комнате), датчик реагирует на него. Аналогично, когда определенная часть вашего кода выполняется, аспект может “реагировать” на это, выполняя нужные действия. 

Зачем это нужно?

Представьте, что у вас есть огромный пазл, где каждая деталька — это часть вашего приложения. Аспекты позволяют нам не изменять каждую детальку отдельно, а “налепить” на несколько из них стикер с дополнительной информацией или функциональностью. Это экономит время, уменьшает ошибки и делает код более чистым и организованным.

В больших проектах аспекты становятся незаменимыми, потому что представьте, что при изменении требований вам нужно менять одну и ту же функцию в десятках или даже сотнях мест. С аспектами вы просто меняете функциональность один раз, и она автоматически применяется везде, где нужно.

Аспекты в Spring AOP — это способ организовать “сквозную” функциональность в вашем приложении без необходимости менять основной код. Это как магические стикеры, которые вы можете приклеить к любой части вашего кода, чтобы добавить дополнительное поведение или функциональность. 


Примеры использования аспектов в Spring AOP

1. Логирование методов 

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>


@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBeforeMethodCall(JoinPoint joinPoint) {
System.out.println("Метод " + joinPoint.getSignature().getName() + "был вызван");
}
}

В этом примере @Before говорит о том, что аспект должен выполняться перед вызовом метода, а выражение в execution() указывает на то, какие именно методы нужно “перехватить”. В данном случае перехватываются все методы из всех классов в пакете com.example.service. 

2. Измерение времени выполнения

@Aspect
@Component
public class PerformanceAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object measureMethodExecutionTime(ProceedingJoinPoint
joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long elapsedTime = System.currentTimeMillis() - start;
System.out.println("Метод " + joinPoint.getSignature().getName() + "выполнился за " + elapsedTime + " миллисекунд");
return result;
}
}

Здесь используется аннотация @Around, которая позволяет аспекту выполниться до и после метода, а также вокруг него. 

3. Изменение возвращаемого значения 

Аспекты также могут изменять возвращаемое значение метода

@Aspect
@Component
public class ChangeReturnValueAspect {
@AfterReturning(pointcut = "execution(* com.example.service.getName(..))",
returning = "result")
public void changeName(JoinPoint joinPoint, String result) {
result = "Измененное имя";
}
}

В этом примере после вызова метода getName из пакета com.example.service, его возвращаемое значение будет изменено на “Измененное имя”.

Эти примеры показывают базовые возможности Spring AOP и то, как вы можете использовать аспекты для добавления дополнительной функциональности в ваш код без изменения самого кода.