Прокси и AOP Proxy

Хорошо, друзья, мы уже немного освоились в мире AOP, но сейчас перед нами стоит еще одна дверь в глубины магии Spring’а. Внимание, сейчас будет очень интересно!

Как Spring создаёт прокси для AOP?

Когда мы говорим о применении аспектов к нашим компонентам в Spring, мы на самом деле говорим о создании “прокси”. Прокси — это своего рода “посредник” между вызывающим и целевым объектом. Spring создает эти прокси-объекты, чтобы вмешаться в вызов метода и выполнить нужные аспекты перед или после нашего основного метода.

Проще говоря, если у вас есть сервис, и вы хотите применить к нему логирование с помощью AOP, Spring создаст “фальшивую” копию вашего сервиса (прокси), которая будет выполнять логирование, а затем перенаправлять вызов на ваш реальный сервис.

JDK Dynamic Proxy vs. CGLIB proxy

Окей, так как же Spring создает эти прокси? Здесь у нас есть два основных механизма:

1. JDK Dynamic Proxy: Этот метод создает прокси для интерфейсов. Если ваш компонент или сервис реализует какой-либо интерфейс, Spring, как правило, использует этот метод. Под капотом здесь используется рефлексия Java, чтобы динамически создать новый объект, который реализует тот же интерфейс, что и ваш целевой объект.

2. CGLIB proxy: А что, если у вас класс, который не реализует никакого интерфейса? Здесь на помощь приходит CGLIB. Этот механизм создает подкласс вашего целевого класса. Внешне он выглядит и ведет себя как ваш оригинальный класс, но внутри он добавляет логику для аспектов.


Пример: Допустим, у вас есть такой сервис:

public class SimpleService {
public void doSomething() {
// ваш код
}
}


Если вы хотите применить к нему аспект, и используете CGLIB, Spring создаст что-то вроде: 

public class SimpleService$$EnhancerBySpringCGLIB extends
SimpleService {
@Override
public void doSomething() {
// логика аспекта (например, логирование)
super.doSomething(); // вызов оригинального метода
}
}


А когда какой метод выбирать?

Spring автоматически решает, какой из механизмов использовать. Если ваш класс реализует интерфейс, Spring, скорее всего, будет использовать JDK Dynamic Proxy. Если нет интерфейса, то выбор падает на CGLIB. Но вы также можете явно указать Spring’у, какой механизм использовать, если у вас есть для этого особые причины.

Проксирование — это сердце магии AOP в Spring. Именно благодаря этим прокси-объектам Spring может применять наши аспекты к целевым компонентам. 

Будь то JDK Dynamic Proxy или CGLIB, оба метода служат одной цели: делать ваш код чище и позволять разделить ответственность, используя аспекты.