Перейти к основному содержимому

Сравнение Spring AOP и AspectJ

· 8 мин. чтения

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Введение

Сегодня существует несколько доступных библиотек АОП, и они должны отвечать на ряд вопросов:

  • Совместимо ли оно с моим существующим или новым приложением?
  • Где я могу реализовать АОП?
  • Как быстро он будет интегрироваться с моим приложением?
  • Каковы издержки производительности?

В этой статье мы рассмотрим ответы на эти вопросы и познакомим вас со Spring AOP и AspectJ — двумя самыми популярными платформами АОП для Java.

2. Концепции АОП

Прежде чем мы начнем, давайте быстро и подробно рассмотрим термины и основные понятия:

  • Аспект — стандартный код/функция, разбросанные по нескольким местам в приложении и обычно отличающиеся от фактической бизнес-логики (например, управление транзакциями). Каждый аспект фокусируется на определенной сквозной функциональности.
  • Точка соединения — это конкретная точка во время выполнения программ, таких как выполнение метода, вызов конструктора или назначение поля.
  • Совет — действие, предпринятое аспектом в конкретной точке соединения.
  • Pointcut — регулярное выражение, соответствующее точке соединения. Каждый раз, когда любая точка соединения соответствует pointcut, выполняется указанный совет, связанный с этим pointcut.
  • Плетение - процесс связывания аспектов с целевыми объектами для создания рекомендуемого объекта.

3. Spring АОП и AspectJ

Теперь давайте обсудим Spring AOP и AspectJ по нескольким направлениям, таким как возможности, цели, плетение, внутренняя структура, точки соединения и простота.

3.1. Возможности и цели

Проще говоря, Spring AOP и AspectJ преследуют разные цели.

Spring AOP стремится предоставить простую реализацию АОП в Spring IoC для решения наиболее распространенных проблем, с которыми сталкиваются программисты. Он не предназначен как полное решение АОП — его можно применять только к bean-компонентам, которыми управляет контейнер Spring.

С другой стороны, AspectJ — это оригинальная АОП-технология, целью которой является предоставление комплексного АОП-решения. Он более надежен, но и значительно сложнее, чем Spring AOP. Также стоит отметить, что AspectJ можно применять ко всем предметным объектам.

3.2. Ткачество

И AspectJ, и Spring AOP используют разные типы плетения, которые влияют на их поведение в отношении производительности и простоты использования.

AspectJ использует три разных типа плетения:

  1. Плетение во время компиляции : компилятор AspectJ принимает в качестве входных данных как исходный код нашего аспекта, так и наше приложение и создает файлы сплетенных классов в качестве выходных данных.
  2. Плетение после компиляции : это также известно как бинарное плетение. Он используется для объединения существующих файлов классов и JAR-файлов с нашими аспектами.
  3. Переплетение во время загрузки : это точно так же, как предыдущее бинарное переплетение, с той разницей, что переплетение откладывается до тех пор, пока загрузчик классов не загрузит файлы классов в JVM.

Для получения более подробной информации о самом AspectJ перейдите к этой статье .

Поскольку AspectJ использует переплетение времени компиляции и загрузки классов, Spring AOP использует переплетение времени выполнения .

При сплетении во время выполнения аспекты переплетаются во время выполнения приложения с использованием прокси-серверов целевого объекта — с использованием либо динамического прокси-сервера JDK, либо прокси-сервера CGLIB (которые обсуждаются в следующем пункте):

./b26b40a5bcb52522b03d81f5ecc30eb9.png

3.3. Внутренняя структура и применение

Spring AOP — это среда АОП на основе прокси. Это означает, что для реализации аспектов целевых объектов будут созданы прокси этого объекта. Это достигается одним из двух способов:

  1. Динамический прокси JDK — предпочтительный способ для Spring AOP. Всякий раз, когда целевой объект реализует хотя бы один интерфейс, будет использоваться динамический прокси JDK.
  2. Прокси-сервер CGLIB — если целевой объект не реализует интерфейс, можно использовать прокси-сервер CGLIB.

Подробнее о механизмах проксирования Spring AOP мы можем узнать из официальной документации .

AspectJ, с другой стороны, ничего не делает во время выполнения, поскольку классы компилируются непосредственно с аспектами.

И поэтому, в отличие от Spring AOP, он не требует никаких шаблонов проектирования. Чтобы вплести аспекты в код, он вводит свой компилятор, известный как компилятор AspectJ (ajc), с помощью которого мы компилируем нашу программу, а затем запускаем ее, предоставляя небольшую (< 100 КБ) библиотеку времени выполнения.

3.4. Точки соединения

В разделе 3.3 мы показали, что Spring AOP основан на шаблонах прокси. Из-за этого ему необходимо создать подкласс целевого класса Java и соответствующим образом применить сквозные аспекты.

Но это связано с ограничением. Мы не можем применять сквозные аспекты (или аспекты) к классам, которые являются «финальными», потому что их нельзя переопределить, и, следовательно, это приведет к исключению во время выполнения.

То же самое относится к статическим и окончательным методам. Аспекты Spring не могут быть применены к ним, потому что они не могут быть переопределены. Следовательно, Spring AOP из-за этих ограничений поддерживает только точки соединения выполнения метода.

Однако AspectJ вплетает сквозные проблемы непосредственно в фактический код перед выполнением. В отличие от Spring AOP, он не требует создания подкласса целевого объекта и, таким образом, поддерживает множество других точек соединения. Ниже приводится сводка поддерживаемых точек соединения:

   | Точка присоединения    | Поддерживается Spring АОП    | Аспект J Поддерживается   | 
| Вызов метода | Нет | Да |
| Выполнение метода | Да | Да |
| Вызов конструктора | Нет | Да |
| Выполнение конструктора | Нет | Да |
| Выполнение статического инициализатора | Нет | Да |
| Инициализация объекта | Нет | Да |
| Ссылка на поле | Нет | Да |
| Полевое назначение | Нет | Да |
| Выполнение обработчика | Нет | Да |
| Исполнение совета | Нет | Да |

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

Это очевидно, потому что, когда мы вызываем метод в том же классе, мы не вызываем метод прокси, который предоставляет Spring AOP. Если нам нужна эта функциональность, нам нужно определить отдельный метод в разных bean-компонентах или использовать AspectJ.

3.5. Простота

Spring AOP, очевидно, проще, потому что он не вводит никакого дополнительного компилятора или ткача между нашим процессом сборки. Он использует переплетение во время выполнения и поэтому легко интегрируется с нашим обычным процессом сборки. Хотя это выглядит просто, оно работает только с bean-компонентами, которыми управляет Spring.

Однако, чтобы использовать AspectJ, нам необходимо ввести компилятор AspectJ (ajc) и переупаковать все наши библиотеки (если только мы не переключимся на посткомпиляцию или переплетение во время загрузки).

Это, конечно, сложнее, чем предыдущее, потому что в нем представлены инструменты AspectJ Java (которые включают компилятор (ajc), отладчик (ajdb), генератор документации (ajdoc), браузер структуры программы (ajbrowser)), которые мы необходимо интегрировать либо с нашей IDE, либо с инструментом сборки.

3.6. Производительность

Что касается производительности, переплетение во время компиляции намного быстрее, чем переплетение во время выполнения . Spring AOP — это фреймворк на основе прокси, поэтому прокси создаются во время запуска приложения. Кроме того, есть еще несколько вызовов методов на аспект, что негативно сказывается на производительности.

С другой стороны, AspectJ вплетает аспекты в основной код перед выполнением приложения, и, таким образом, нет дополнительных накладных расходов во время выполнения, в отличие от Spring AOP.

По этим причинам тесты показывают, что AspectJ почти в 8–35 раз быстрее, чем Spring AOP.

4. Резюме

Эта краткая таблица суммирует основные различия между Spring AOP и AspectJ:

   | Весенний АОП    | АспектJ   | 
| Реализовано на чистой Java | Реализовано с использованием расширений языка программирования Java. |
| Нет необходимости в отдельном процессе компиляции | Требуется компилятор AspectJ (ajc), если не настроен LTW |
| Доступно только плетение во время выполнения | Прошивка во время выполнения недоступна. Поддерживает время компиляции, пост-компиляцию и время загрузки Weaving |
| Менее мощный — поддерживает только переплетение на уровне метода. | Более мощный — может объединять поля, методы, конструкторы, статические инициализаторы, окончательные классы/методы и т. д. |
| Может быть реализован только на bean-компонентах, управляемых контейнером Spring. | Может быть реализован на всех предметных объектах |
| Поддерживает только точки выполнения метода | Поддержка всех точечных сокращений |
| Прокси создаются из целевых объектов, и на эти прокси накладываются аспекты | Аспекты вплетаются непосредственно в код перед выполнением приложения (до выполнения) |
| Гораздо медленнее, чем AspectJ | Лучшая производительность |
| Легко учиться и применять | Сравнительно сложнее, чем Spring AOP |

5. Выбор правильного фреймворка

Если мы проанализируем все аргументы, приведенные в этом разделе, то начнем понимать, что дело вовсе не в том, что один фреймворк лучше другого.

Проще говоря, выбор сильно зависит от наших требований:

  • Фреймворк: если приложение не использует фреймворк Spring, у нас нет другого выбора, кроме как отказаться от идеи использования Spring AOP, потому что он не может управлять чем-либо, что находится за пределами досягаемости контейнера Spring. Однако, если наше приложение создано полностью с использованием среды Spring, мы можем использовать Spring AOP, так как его легко изучить и применить.
  • Гибкость. Учитывая ограниченную поддержку точек соединения, Spring AOP не является полным АОП-решением, но решает наиболее распространенные проблемы, с которыми сталкиваются программисты. Хотя, если мы хотим копнуть глубже и максимально использовать АОП, и нам нужна поддержка из широкого спектра доступных точек соединения, то AspectJ — это выбор.
  • Производительность: если мы используем ограниченные аспекты, тогда есть тривиальные различия в производительности. Но бывают случаи, когда приложение имеет более десятков тысяч аспектов. Мы не хотели бы использовать рантайм-ткачество в таких случаях, поэтому было бы лучше выбрать AspectJ. Известно, что AspectJ в 8–35 раз быстрее, чем Spring AOP.
  • Лучшее из обоих: обе эти платформы полностью совместимы друг с другом. Мы всегда можем воспользоваться преимуществами Spring AOP, когда это возможно, и по-прежнему использовать AspectJ для поддержки точек соединения, которые не поддерживаются предыдущими версиями.

6. Заключение

В этой статье мы проанализировали как Spring AOP, так и AspectJ в нескольких ключевых областях.

Мы сравнили два подхода к АОП как по гибкости, так и по тому, насколько легко они подходят для нашего приложения.