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

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

1. Вступление

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

  • Совместимо ли это с моим существующим или новым приложением?

  • Где я могу реализовать АОП?

  • Как быстро он интегрируется с моим приложением?

  • Каковы потери производительности?

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

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

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

  • Аспект - ** стандартный код / ​​функция, которая разбросана по нескольким местам в приложении и обычно отличается от фактической бизнес-логики (например, управление транзакциями). Каждый аспект фокусируется на определенной сквозной функциональности

  • Точка соединения - ** это определенная точка во время выполнения таких программ, как выполнение метода, вызов конструктора или присвоение поля.

  • Совет - действие, предпринимаемое аспектом в определенной точке соединения

  • Pointcut - регулярное выражение, соответствующее точке соединения. Каждый раз, когда любая точка соединения совпадает с точкой, выполняется указанная рекомендация, связанная с этой точкой.

  • Плетение - процесс связывания аспектов с целевыми объектами для создания рекомендованного объекта

3. Spring AOP и AspectJ

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

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

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

Spring AOP стремится обеспечить простую реализацию AOP в Spring IoC для решения наиболее распространенных проблем, с которыми сталкиваются программисты. It is not intended as a complete AOP solution - его можно применять только к bean-компонентам, которые управляются контейнером Spring.

С другой стороны,AspectJ is the original AOP technology which aims to provide complete AOP solution. Он более надежен, но также значительно сложнее, чем Spring AOP. Также стоит отметить, что AspectJ можно применять ко всем объектам домена.

3.2. ткачество

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

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

  1. Compile-time weaving: Компилятор AspectJ принимает в качестве входных данных как исходный код нашего аспекта, так и нашего приложения, а в качестве выходных данных создает сплетенные файлы классов.

  2. Post-compile weaving: это также известно как двоичное переплетение. Он используется для объединения существующих файлов классов и файлов JAR с нашими аспектами

  3. Load-time weaving: это точно так же, как и предыдущее двоичное переплетение, с той разницей, что переплетение откладывается до тех пор, пока загрузчик классов не загрузит файлы классов в JVM.

Для получения более подробной информации о самом AspectJ,head on over to this article.

AspectJ использует время компиляции и время загрузки классов,Spring AOP makes use of runtime weaving.

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

image

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

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

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

  2. Прокси-сервер CGLIB - если целевой объект не реализует интерфейс, можно использовать прокси-сервер CGLIB.

Мы можем узнать больше о механизмах проксирования Spring AOP изthe official docs.

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

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

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

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

Но это идет с ограничением. We cannot apply cross-cutting concerns (or aspects) across classes that are “final” because they cannot be overridden and thus it would result in a runtime exception.с

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

ОднакоAspectJ weaves the cross-cutting concerns directly into the actual code before runtime., в отличие от Spring AOP, не требует подкласса целевого объекта и, таким образом, поддерживает многие другие точки соединения. Ниже приведен список поддерживаемых точек соединения:

Точка соединения Поддерживается Spring AOP AspectJ Поддерживается

Вызов метода

No

Yes

Выполнение метода

Yes

Yes

Вызов конструктора

No

Yes

Конструктор Выполнение

No

Yes

Выполнение статического инициализатора

No

Yes

Инициализация объекта

No

Yes

Ссылка на поле

No

Yes

Полевое задание

No

Yes

Выполнение обработчика

No

Yes

Выполнение совета

No

Yes

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

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

3.5. Простота

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

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

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

3.6. Спектакль

Что касается производительности,compile-time weaving is much faster than runtime weaving. Spring AOP - это основанная на прокси среда, поэтому во время запуска приложения создается прокси. Кроме того, есть еще несколько вызовов методов для каждого аспекта, что отрицательно влияет на производительность.

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

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

4. Резюме

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

Весенний АОП AspectJ

Реализовано на чистой Java

Реализовано с использованием расширений языка программирования Java.

Нет необходимости в отдельном процессе компиляции

Требуется компилятор AspectJ (ajc), если не настроен LTW

Доступно только runtime плетение

Время выполнения плетения недоступно. Поддерживает ткачество во время компиляции, после компиляции и загрузки

Менее мощный - поддерживает только переплетение на уровне метода

Более мощный - может создавать поля, методы, конструкторы, статические инициализаторы, конечный класс / методы и т. Д.

Может быть реализовано только на beans, управляемом контейнером Spring

Может быть реализовано на всех объектах домена

Поддерживает только выполнение метода pointcut

Поддержка всех точек

Прокси создаются из целевых объектов, и к этим прокси применяются аспекты.

Аспекты встраиваются непосредственно в код перед запуском приложения (до выполнения)

Намного медленнее, чем AspectJ

Лучшая производительность

Легко учиться и применять

Сравнительно сложнее, чем Spring AOP

5. Выбор правильной структуры

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

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

  • Фреймворк: если приложение не использует фреймворк Spring, у нас нет другого выбора, кроме как отказаться от идеи использования Spring AOP, потому что оно не может управлять чем-либо, что находится вне досягаемости контейнера Spring. Однако, если наше приложение полностью создано с использованием среды Spring, мы можем использовать Spring AOP, поскольку его легко изучить и применить.

  • Гибкость. Учитывая ограниченную поддержку точек соединения, Spring AOP не является полным решением AOP, но он решает наиболее распространенные проблемы, с которыми сталкиваются программисты. Хотя если мы хотим копать глубже и максимально использовать возможности AOP и хотим поддерживать широкий диапазон доступных точек соединения, то AspectJ - это выбор

  • Производительность: если мы используем ограниченные аспекты, то есть тривиальные различия в производительности. Но иногда бывают случаи, когда приложение имеет более десятков тысяч аспектов. Мы не хотели бы использовать ткачество во время выполнения в таких случаях, поэтому было бы лучше выбрать AspectJ. Известно, что AspectJ в 8-35 раз быстрее Spring AOP

  • Лучшее из обоих: обе эти платформы полностью совместимы друг с другом. Мы всегда можем воспользоваться Spring AOP, когда это возможно, и по-прежнему использовать AspectJ, чтобы получить поддержку точек соединения, которые не поддерживаются первым.

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

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

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