Создаешь ли новый класс при проксировании объекта
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Проксирование объектов и создание новых классов
Да, при проксировании объекта динамически создаётся новый класс, который наследует интерфейсы оригинального объекта и перехватывает вызовы методов.
Как это работает
1. Java Dynamic Proxy (java.lang.reflect.Proxy)
Это встроенный в Java механизм для создания proxy-объектов. Когда вы вызываете Proxy.newProxyInstance(), JVM динамически генерирует новый класс, который:
- Реализует все указанные интерфейсы
- Перехватывает все вызовы методов через
InvocationHandler - Передаёт вызовы оригинальному объекту
public interface UserService {
String getUser(int id);
void saveUser(String name);
}
public class UserServiceImpl implements UserService {
@Override
public String getUser(int id) {
return "User " + id;
}
@Override
public void saveUser(String name) {
System.out.println("Saving: " + name);
}
}
// Создание proxy
UserService original = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
(Object proxyObj, Method method, Object[] args) -> {
System.out.println("[LOG] Вызов метода: " + method.getName());
long start = System.currentTimeMillis();
Object result = method.invoke(original, args);
long duration = System.currentTimeMillis() - start;
System.out.println("[LOG] Выполнено за " + duration + "ms");
return result;
}
);
proxy.getUser(1); // Вывод: [LOG] Вызов метода: getUser ...
proxy.saveUser("John"); // Вывод: [LOG] Вызов метода: saveUser ...
2. CGLib - Proxy по классам
В отличие от Dynamic Proxy, которая работает только с интерфейсами, CGLib может проксировать конкретные классы через наследование и создание подклассов:
public class UserService {
public String getUser(int id) {
return "User " + id;
}
}
// CGLib создаёт подкласс UserService
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
System.out.println("[LOG] Вызов: " + method.getName());
return proxy.invokeSuper(obj, args);
});
UserService proxyService = (UserService) enhancer.create();
proxyService.getUser(1);
Отличия подходов
| Аспект | Dynamic Proxy | CGLib |
|---|---|---|
| Что проксирует | Интерфейсы | Классы |
| Встроена в JDK | Да | Нет (отдельная библиотека) |
| Переопределение final методов | Нет | Да |
| Производительность | Выше | Ниже (генерация bytecode) |
Практическое применение
Spring AOP использует обе технологии:
- По умолчанию Dynamic Proxy (если есть интерфейсы)
- CGLib (если класс без интерфейсов)
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Before: " + pjp.getSignature());
Object result = pjp.proceed();
System.out.println("After: " + pjp.getSignature());
return result;
}
}
Ключевой момент
Прокси — это обёртка над оригинальным объектом, которая не изменяет сам оригинальный класс, а создаёт новый класс (либо через реализацию интерфейсов, либо через наследование), который имитирует его поведение и добавляет дополнительную логику перед/после вызовов методов.