Типы Proxy, поддерживаемые Spring AOP


Spring AOP (Aspect-Oriented Programming) — это фреймворк, предназначенный для создания аспектно-ориентированных приложений в рамках платформы Spring. Он предоставляет возможность реализации перехватчиков (аспектов) для выполнения дополнительных действий во время выполнения основной логики приложения.

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

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

Выбор типа прокси в Spring AOP автоматически определяется фреймворком на основе доступных классов и интерфейсов. Однако, при желании, можно явно указать тип прокси, используя настройки в конфигурационном файле Spring. Это делается с помощью атрибута proxy-target-class в элементе aop:config.

Типы прокси, поддерживаемые Spring AOP:

Spring AOP поддерживает два основных типа прокси: JDK-прокси и CGLIB-прокси.

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

2. CGLIB-прокси: Если целевой объект не реализует никакие интерфейсы, то Spring AOP использует CGLIB-прокси для создания прокси-объекта. CGLIB-прокси создает подкласс целевого объекта и переопределяет его методы для внедрения логики аспектов. CGLIB-прокси используется для проксирования классов, которые не являются интерфейсами.

Динамические прокси

Spring AOP поддерживает два типа прокси: статические и динамические. В этом разделе мы рассмотрим динамические прокси в Spring AOP.

Динамические прокси создаются во время выполнения программы, основываясь на интерфейсах или классах, которые необходимо проксировать. Spring AOP использует библиотеку CGLIB или JDK Dynamic Proxy для создания динамических прокси.

При использовании CGLIB, Spring AOP создает подкласс целевого класса, который расширяет целевой класс и переопределяет его методы, применяя аспекты. Затем Spring AOP создает экземпляр этого подкласса во время выполнения и использует его вместо исходного целевого класса.

При использовании JDK Dynamic Proxy, Spring AOP создает прокси-объект, который реализует все интерфейсы, реализованные целевым классом. Затем Spring AOP использует этот прокси-объект вместо исходного целевого объекта и применяет аспекты.

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

Однако, использование динамических прокси может иметь некоторые накладные расходы в производительности, поскольку создание и использование прокси-объектов требует дополнительных вычислений и памяти.

CGLIB-прокси

При использовании CGLIB-прокси создается подкласс целевого класса, который переопределяет методы, помеченные аннотацией @Before, @After и другими аннотациями, используемыми в Spring AOP. При вызове методов целевого класса сначала выполняются соответствующие советы, а затем уже сам метод целевого класса.

Преимуществом использования CGLIB-прокси является отсутствие необходимости в наличии интерфейса у целевого класса. Однако генерация дополнительного класса на лету может привести к некоторому снижению производительности в сравнении с JDK-прокси.

JDK-прокси

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

Созданный JDK-прокси-класс оборачивает целевой объект и перехватывает вызовы методов, предоставляя возможность выполнить дополнительные действия до или после вызова метода и/или изменить его результат.

Преимущества JDK-прокси:

  • Простота использования: JDK-прокси не требует дополнительных библиотек или зависимостей;
  • Поддержка только интерфейсов: JDK-прокси позволяет проксировать только интерфейсы, что может быть полезно в случае, когда нужно применить аспекты только к определенным методам интерфейса;
  • Высокая производительность: JDK-прокси работает непосредственно с байткодом и обеспечивает высокую производительность при выполнении методов прокси-объекта.

Однако JDK-прокси имеет некоторые ограничения. Например, он не поддерживает проксирование методов классов, только интерфейсов. Кроме того, JDK-прокси не может перехватывать вызовы методов, которые происходят внутри самого целевого объекта, то есть вызовы, которые не проходят через его публичные методы.

Клиентские прокси

Для использования клиентских прокси в Spring AOP необходимо выполнить следующие шаги:

  1. Определить интерфейс, описывающий методы бизнес-логики.
  2. Создать класс, реализующий этот интерфейс и содержащий саму бизнес-логику.
  3. Определить советы, которые будут применены к методам бизнес-логики.
  4. Создать экземпляр клиентского прокси с помощью фабричного метода ProxyFactoryBean.
  5. Настроить клиентский прокси, указав интерфейс, реализацию и список советов.
  6. Использовать клиентский прокси для вызова методов бизнес-логики.

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

Серверные прокси

Spring AOP поддерживает три типа прокси: JDK-прокси, CGLIB-прокси и аспекты контейнера (или аспекты Spring).

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

CGLIB-прокси, с другой стороны, создает подкласс целевого объекта и переопределяет его методы, добавляя поведение аспектов. CGLIB-прокси используются для проксирования классов, не реализующих интерфейсы.

Аспекты контейнера (или аспекты Spring) — это особый тип прокси, который предоставляет Spring Framework. Они не создают прокси-объекты, а применяют аспекты непосредственно к целевому объекту. Это делает их особенно эффективными для применения аспектов ко множеству объектов одновременно.

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

Tип проксиПреимуществаНедостатки
JDK-прокси— Поддерживает проксирование интерфейсов классов.
— Легкий и эффективный.
— Не поддерживает проксирование финальных классов.
— Может привести к ClassCastException, если целевой объект не реализует интерфейсы класса.
CGLIB-прокси— Поддерживает проксирование классов, не реализующих интерфейсы.
— Более гибкий в выборе целей для проксирования.
— Чуть более сложный и медленный, чем JDK-прокси.
— Не поддерживает проксирование финальных методов.
Аспекты контейнера— Не создают прокси-объекты, а применяют аспекты непосредственно к целевому объекту.
— Особенно эффективны для применения аспектов ко множеству объектов одновременно.
— Нельзя применять к финальным классам и методам.
— Может быть несовместим с некоторыми библиотеками и инструментами.

Чистые прокси

Чистые прокси представляют собой прокси-объекты, которые реализуют интерфейсы бинов. При создании прокси-объекта Spring AOP создает динамический прокси, используя JDK Dynamic Proxy, если бин реализует какой-либо интерфейс. В противном случае, если бин не реализует интерфейс, Spring AOP создает прокси-объект с помощью CGLIB Proxy, который наследуется от целевого бина и может переопределить его методы.

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

Добавить комментарий

Вам также может понравиться