Ответ
Нет, Java Dynamic Proxy создает объект другого типа.
1. Как работает java.lang.reflect.Proxy:
- Создает новый класс во время выполнения, который реализует те же интерфейсы, что и оригинальный объект.
- Этот прокси-класс не наследует от класса оригинального объекта.
- Все вызовы методов перехватываются
InvocationHandler.
2. Пример:
interface UserService {
String getUserName(int id);
void deleteUser(int id);
}
class UserServiceImpl implements UserService {
public String getUserName(int id) {
return "User_" + id;
}
public void deleteUser(int id) {
System.out.println("Deleting user " + id);
}
}
// Создание прокси
UserService realService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class}, // Только интерфейсы!
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Логирование до вызова
System.out.println("Calling method: " + method.getName());
// Вызов оригинального метода
Object result = method.invoke(realService, args);
// Логирование после вызова
System.out.println("Method completed");
return result;
}
}
);
// proxy - это НЕ UserServiceImpl, а объект сгенерированного класса
System.out.println(proxy.getClass()); // com.sun.proxy.$Proxy0
System.out.println(proxy instanceof UserServiceImpl); // false
System.out.println(proxy instanceof UserService); // true
3. Ограничения Dynamic Proxy:
- Работает только с интерфейсами.
- Не может перехватывать вызовы
finalметодов. - Не проксирует вызовы внутри класса (self-invocation).
4. Альтернативы для классов:
- CGLIB/ByteBuddy: Создают подкласс, переопределяя методы.
- Spring AOP: Использует CGLIB по умолчанию для классов без интерфейсов.
5. Практическое применение:
- Транзакции (Spring
@Transactional) - Кеширование
- Логирование
- Безопасность (проверка прав доступа)