← Назад к вопросам

Как создаются Proxy в String Boot 2

2.0 Middle🔥 241 комментариев
#SOLID и паттерны проектирования#Spring Boot и Spring Data#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как создаются Proxy в Spring Boot 2

Proxy-объекты в Spring Boot 2 — это один из фундаментальных механизмов фреймворка, используемый для реализации таких функций как транзакции, кэширование, логирование и безопасность. Давайте разберёмся, как они работают.

Основные механизмы создания Proxy

Spring использует два основных подхода для создания proxy-объектов:

  1. JDK Dynamic Proxy — для интерфейсов
  2. CGLIB — для классов без интерфейсов

JDK Dynamic Proxy

Spring создает proxy на основе интерфейсов, используя встроенный механизм Java:

// Интерфейс
public interface UserService {
    User findUser(String id);
    void saveUser(User user);
}

// Реализация
@Service
public class UserServiceImpl implements UserService {
    @Override
    @Transactional
    public void saveUser(User user) {
        // сохранение пользователя
    }
}

Spring автоматически оборачивает UserServiceImpl в proxy, реализующий UserService. Когда вызывается метод saveUser(), proxy перехватывает вызов, открывает транзакцию, выполняет исходный метод, затем закрывает транзакцию.

CGLIB Proxy

Если класс не реализует интерфейсы, Spring использует CGLIB (Code Generation Library):

@Service
public class ProductService {
    @Transactional
    public void updateProduct(Product product) {
        // обновление товара
    }
}

CGLIB создает подкласс ProductService и переопределяет методы, добавляя логику proxy.

AspectJ и BeanPostProcessor

Механизм работает через BeanPostProcessor:

@Component
@Aspect
public class LoggingAspect {
    
    @Around("@annotation(Loggable)")
    public Object logExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Вызов метода: " + methodName);
        
        Object result = joinPoint.proceed(); // вызов оригинального метода
        
        System.out.println("Метод завершён: " + methodName);
        return result;
    }
}

Конфигурация Proxy

В application.yml или application.properties можно управлять поведением:

spring:
  aop:
    proxy-target-class: true  # Использовать CGLIB для всех классов
  • proxy-target-class: true — CGLIB всегда
  • proxy-target-class: false — JDK для интерфейсов, CGLIB для классов

Важные особенности

Ограничение с приватными методами: Proxy не перехватывают приватные методы, так как они не переопределяются:

@Service
public class UserService {
    @Transactional
    public void publicMethod() {
        privateMethod(); // Транзакция НЕ будет открыта!
    }
    
    @Transactional
    private void privateMethod() {
        // Это не сработает
    }
}

Вызов через this: Если внутри класса вызвать другой метод через this, proxy не будет применён:

@Service
public class OrderService {
    @Transactional
    public void createOrder() {
        this.validateOrder(); // Proxy НЕ перехватит
    }
    
    @Transactional
    public void validateOrder() { }
}

Best Practices

  • Используй интерфейсы для сервисов — это явно показывает контракт
  • Помни про ограничения proxy на приватные методы
  • Для критичных мест используй явные транзакции через TransactionTemplate
  • Избегай вызовов через this в методах с @Transactional

Spring Boot 2 делает работу с proxy прозрачной, но понимание механизма критично для отладки и оптимизации приложения.