Ответ
Spring Framework поддерживает три основных механизма проксирования, каждый со своей областью применения.
1. JDK Dynamic Proxy (Proxy на основе интерфейсов)
- Принцип работы: Использует встроенные возможности Java (
java.lang.reflect.Proxy). Создает прокси-объект, реализующий те же интерфейсы, что и целевой объект. - Когда используется: По умолчанию, если бин реализует хотя бы один интерфейс.
- Ограничение: Не может проксировать классы, не имеющие интерфейсов, или вызовы методов, объявленных в самом классе (не в интерфейсе).
public interface UserService {
void createUser();
}
@Service
public class UserServiceImpl implements UserService {
@Override
@Transactional // Для этого вызова будет создан JDK Dynamic Proxy
public void createUser() {
// логика
}
}
2. CGLIB Proxy (Proxy на основе наследования)
- Принцип работы: Создает подкласс целевого класса во время выполнения (байт-кодовая генерация) и переопределяет его методы.
- Когда используется: Когда целевой класс не реализует интерфейсы (например, конкретный класс). Для активации необходимо установить
proxyTargetClass = true. - Ограничение: Не может переопределить
finalметоды или проксироватьfinalклассы.
@Service
public class ConcreteService { // Нет интерфейса
@Transactional // Для этого вызова будет создан CGLIB Proxy
public void process() {
// логика
}
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // Принудительное использование CGLIB
public class AppConfig {}
3. AspectJ Compile-time/Load-time Weaving
- Принцип работы: Модифицирует байт-код класса на этапе компиляции или загрузки в JVM. Не использует стандартные прокси Spring.
- Когда используется: Для наиболее сложных сценариев, где требуется проксирование
privateметодов, конструкторов или полей, а также для максимальной производительности. - Ограничение: Требует дополнительной настройки сборки (AspectJ compiler) или агента загрузки.
Сравнение:
- JDK Proxy: Быстрее создается, вызовы через интерфейс медленнее. Стандартная Java.
- CGLIB: Медленнее создается, вызовы методов быстрее. Требует библиотеки CGLIB в classpath.
- AspectJ: Наибольшая гибкость и производительность во время выполнения, но сложнее в настройке.