Рубрики
Без рубрики

Аспектно-ориентированное программирование с Java и Spring Boot

В этом блоге рассматриваются основы аспектно-ориентированного программирования (AOP). Я покажу простой рабочий пример… Помечено как java, aop, весенняя загрузка, новички.

Аспектно-Ориентированное Программирование (Серия из 2 Частей)

Этот блог охватывает основы Аспектно-ориентированного программирования (АОП). Я покажу простой рабочий пример AOP: обычная задача, такая как протоколирование вызовов REST, может быть в общем виде определена в Советы , которые затем могут быть применены к различным целевым местам в нашем коде (так называемые Точечные вырезы ) через Аспект .

Для нетерпеливых: вы можете найти конечный результат в моем репозитории Github 🏎️

я сам/aop-демо

Демонстрация для аспектно-ориентированного программирования

Еще в 1996 году, когда Была выпущена Java 1.0, разработчики Java были в восторге от объектно-ориентированного программирования , также называемого ООП. В то время как ООП был одним из основополагающих драйверов для Java, сам язык программирования с тех пор прошел долгий путь и теперь поддерживает многие парадигмы программирования .

Вот список основных парадигм программирования, поддерживаемых в Java (в историческом порядке):

  • Процедурное программирование
  • Объектно-ориентированное программирование (ОП)
  • Функциональное программирование
  • Аспектно-ориентированное программирование (АОП)

В этом посте мы сосредоточимся на AOP и покажем, как создавать аспекты. Вы изучите как основы AOP, так и то, как использовать его с Spring Boot .

У большинства крупных компаний есть руководящие принципы программирования, как и у меня. В одном из наших руководящих принципов говорится, что каждое выполнение конечной точки REST должно регистрироваться (имя метода Java + параметры).

Вот как вы могли бы решить эту проблему:

@RestController
public class MyRestController {
  @GetMapping(path = "/api/hello/")
  public String hello() {
    System.out.println("Method [hello] gets called with 0 parameters");
    return "Hello world!";
  }
}

Приведенный выше фрагмент кода выполняет следующее:

  • @RestController : Убедитесь, что SpringBoot знает, что этот класс содержит конечные точки REST
  • @GetMapping : метод, который отвечает на HTTP-запросы GET
  • System.out.println(...) : придерживайтесь вышеупомянутых рекомендаций по кодированию
  • возвращаемое значение: метод просто возвращает приветственное сообщение типа String

В реалистичном приложении у вас будет много таких вызовов REST во многих разных классах. Выполнение точно такого же ведения журнала во всех этих методах является громоздким . Более того, если рекомендации по кодированию немного изменятся, вам придется изменить сообщение о регистрации в каждом методе.

Вот где AOP приходит на помощь: с помощью AOP мы можем красиво добавлять общие функциональные возможности во многие разные места нашего кода, не вмешиваясь в существующий код . На литературном жаргоне AOP – это все о разделении сквозных проблем. 🤓 На более понятном для человека языке AOP обеспечивает модульность общих задач для разных объектов. 😎

Чтобы начать использовать AOP в Spring Boot с аннотациями AspectJ , , нам необходимо импортировать следующие зависимости в ваш pom.xml


  org.springframework.boot
  spring-boot-starter-aop


  org.aspectj
  aspectjweaver

Давайте создадим функцию, которая выполняет наше требуемое ведение журнала в общем виде:

public void logMethodExecution(JoinPoint joinPoint) {
  String method = joinPoint.getSignature().getName();
  String params = Arrays.toString(joinPoint.getArgs());
  System.out.println("Method [" + method + "] gets called with parameters " + params);
}

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

Итак, куда мы хотим вставить вышеприведенный метод рекомендаций? Ну, мы хотим, чтобы отслеживалась каждая конечная точка REST. Хотя существует множество способов пометить наши конечные точки REST, мы решили использовать пользовательскую аннотацию для определения Точечный разрез :

@Before("@annotation(LogMethod)")
public void logMethodExecution(JoinPoint joinPoint) {...}

Как вы можете видеть, определение Pointcut – это просто однострочное:

  • @Before : мы выполняем консультацию до того, как будет получен ответ на вызов REST
  • @аннотация : мы отмечаем точечные вырезы с помощью аннотации
  • Метод регистрации : это название нашей пользовательской аннотации

Теперь мы готовы отметить наш метод REST нашей пользовательской аннотацией:

@LogMethod
@GetMapping(path = "/api/hello/")
public String hello() {
  return "Hello world!";
}

Обратите внимание, что мы дополнили метод REST аннотацией @LogMethod . Более того, мы удалили ведение журнала внутри метода, теперь это делает наш аспект.

Аспект – это Точечный разрез плюс Совет. Итак, давайте соединим их вместе, и мы получим:

@Aspect
@Component
public class LoggingAspect {

  @Before("@annotation(LogMethod)")
  public void logMethodName(JoinPoint joinPoint) {
    String method = joinPoint.getSignature().getName();
    String params = Arrays.toString(joinPoint.getArgs());
    System.out.println("Method [" + method + "] gets called with parameters " + params);
  }
}

Вот что у нас есть:

  • @@Aspect : Spring Boot ожидает, что все аспекты будут в классах, помеченных @Aspect
  • @До(...) : Точечный разрез
  • имя метода регистрации(...){...} : совет

Итак, все, что мы здесь сделали, это просто объединили ранее показанное выражение точечной резки плюс Советы и заключили все в класс. Принесите шампанское, у нас все готово и мы работаем 🥂

Чтобы завершить, мы должны включить AspectJ для нашей конфигурации Spring :

@Configuration
@EnableAspectJAutoProxy
public class AspectConfig {

}

Помните, что мы хотим иметь возможность работать с бобами при использовании Spring. На данный момент наш класс @RestController содержит только логику вызова REST, но не наш совет. Spring может создавать Прокси-серверы для таких компонентов, которые содержат эту дополнительную логику (Совет), и это включено @EnableAspectJAutoProxy .

Вот и все! Теперь у вас есть полностью работающий пример AOP 😀 💪 🍾

Мы внедрили совет, который следует запускать в любое время, когда выполняется метод с аннотацией @LogMethod . Благодаря нашему подходу AOP мы можем добавить эту аннотацию в будущие методы REST, которые затем будут рекомендованы с тем же аспектом!

Ознакомьтесь с полностью рабочим примером на Github:

я сам/aop-демо

Демонстрация для аспектно-ориентированного программирования

Это простой веб-сервис, который использует AOP. ОСТАЛЬНЫЕ методы рекомендуются по нескольким аспектам.

Зависимости

  • Java JDK 15
  • Знаток:
    • пружинный загрузчик-стартер-aop
    • аспектjweaver

Аспекты для вызовов REST

  • Имя и параметры метода регистрации
  • Длительность регистрации метода

Использование

  • Скомпилировать и запустить веб-службу:
mvn clean install
mvn spring-boot:run
  • Примеры вызовов REST:
GET http://localhost:8080/api/greeting/{name}
GET http://localhost:8080/api/order/{menu}

Пример вывода аспекта

Method [greeting] gets called with parameters [John]
Exeution took [21ms]

Это репозиторий Github также содержит второй совет типа @Вокруг : Каждый раз, когда вызывается метод REST, мы регистрируем время выполнения. Это может пригодиться для измерения, мониторинга и сравнения производительности различных конечных точек REST.

Спасибо за чтение, пожалуйста, оставьте комментарий, если у вас есть какие-либо отзывы или вопросы! 😀

Для любопытных, вот еще несколько материалов для чтения:

AOP праймер и типы советов : В нашем примере мы использовали совет типа @До . В качестве альтернативы вы можете использовать @После , @Вокруг или @Последующий рост .

Точечные вырезы – это предикаты, соответствующие набору точек соединения. Мы использовали точечные вырезы, управляемые аннотациями, но Spring поддерживает гораздо больше типов обозначений. Например, Spring поддерживает выполнение Точечные сокращения, где имя метода должно соответствовать заданному шаблону.

Прокси-серверы AOP : объяснение в официальной документации Spring.

Аспектно-Ориентированное Программирование (Серия из 2 Частей)

Оригинал: “https://dev.to/pmgysel/aspect-oriented-programming-with-java-and-springboot-2nlg”