powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Вопрос по proxy-классам.
18 сообщений из 18, страница 1 из 1
Вопрос по proxy-классам.
    #39175141
ll13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Изучаю java по книге "Java. Библиотека профессионала Хорстманн, Корнелл"
в книге приведен пример трассировки вызова методов объекта используя прокси-класс.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
import java.lang.reflect.*;
import java.util.*;

class TraceHandler implements InvocationHandler{
    
    private Object target;
    
    public TraceHandler(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                
        System.out.print(target);
        System.out.print("." + method.getName() + "(");
        if(args != null){
            for (int i = 0; i < args.length; i++) {
                System.out.print(args[i]);
                if(i < args.length - 1)
                    System.out.print(", ");
            }
        }
        System.out.println(")");
        
        return method.invoke(target, args);         
        
    }
}

public class ProxyTest {

    public static void main(String[] args) {
        
        Object[] elements = new Object[1000];
        for (int i = 0; i < elements.length; i++) {
            Integer value = i + 1;
            InvocationHandler handler = new TraceHandler(value);
            Object proxy = Proxy.newProxyInstance(null , new Class[] {Comparable.class}, handler);
            elements[i] = proxy;
        }
        
        Integer key = new Random().nextInt(elements.length) + 1;
        
        int result = Arrays.binarySearch(elements, key);
   
    }
    
}



Пример полностью рабочий.
Это работает:
Код: java
1.
Arrays.binarySearch(elements, key);


но почему в таком случае не работает?!
Код: java
1.
Arrays.sort(elements);



Выдаются ошибки:
Код: plaintext
1.
2.
3.
4.
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
	at com.sun.proxy.$Proxy0.compareTo(Unknown Source)
	at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:202)
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175247
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13,

Научитесь читать исключения. Исключение, которое указывает на проблему следующее:
Код: java
1.
2.
3.
Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to java.lang.Integer
        at java.lang.Integer.compareTo(Unknown Source)
        ... 10 more


А не то что вы привели.

Объяснять надо исключение или понятно?
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175277
Garrick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowiczll13,

Научитесь читать исключения. Исключение, которое указывает на проблему следующее:
Код: java
1.
2.
3.
Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to java.lang.Integer
        at java.lang.Integer.compareTo(Unknown Source)
        ... 10 more


А не то что вы привели.

И более того, оно даже указывает имя класса и номер строки где возникла проблема.
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175363
ll13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Garrick, Blazkowicz

Насколько я понимаю исключение вызвано невозможностью приведения типа com.sun.proxy.$Proxy0 к java.lang.Integer
Но я никак не могу понять что привело к данной ситуации? Как локализовать и исправить ошибку?
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175375
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13Но я никак не могу понять что привело к данной ситуации? Как локализовать и исправить ошибку?
Это очень грустно слышать.
У вас есть массив Proxy. Для сортировки нужно сравнивать разные элементы коллекции друг с другом.
Для сравнения вызывается метод Comparable.compareTo(). То есть у экземпляра Proxy вызывается метод compareTo и аргументом метода передаётся другой Proxy.
InvocationHandler перехватывает вызов, чего-то там логирует и вызывает метод делегата (у вас о почему-то target).
В target у вас хранится Integer, значит method.invoke(target, args); вызывает Integer.compareTo(args)
В args у вас Proxy. А Integer.compareTo() ожидает только Integer.

Зачем у вас переменные типа Object для хранения Integer это вопрос открытый.
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175413
ll13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczУ вас есть массив Proxy. Для сортировки нужно сравнивать разные элементы коллекции друг с другом.
Для сравнения вызывается метод Comparable.compareTo(). То есть у экземпляра Proxy вызывается метод compareTo и аргументом метода передаётся другой Proxy.
InvocationHandler перехватывает вызов, чего-то там логирует и вызывает метод делегата (у вас о почему-то target).
В target у вас хранится Integer, значит method.invoke(target, args); вызывает Integer.compareTo(args)
В args у вас Proxy. А Integer.compareTo() ожидает только Integer.
Спасибо, проблему понял...
Каким образом можно "правильно" реализовать подобную логику логирования? Где можно посмотреть корректный пример?
Зачем у вас переменные типа Object для хранения Integer это вопрос открытый.
Вопрос этот не ко мне а к авторам книги "Java. Библиотека профессионала Хорстманн, Корнелл"
Пишу ещё раз: Изучаю java по книге "Java. Библиотека профессионала Хорстманн, Корнелл"...
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175421
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13,

Логирование реализовано правильно. Не правильно реализовано делегирования вызова для метода compareTo.
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175434
ll13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczll13,

Логирование реализовано правильно. Не правильно реализовано делегирования вызова для метода compareTo.

Где можно посмотреть пример правильной реализации делегирования?
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175454
ll13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подводя итог по данному вопросу:
1). Есть интерфейс Comparable(содержит один метод compareTo)
2). Есть класс Integer, реализующий данный интерфейс.
3). Есть прокси-класс, перехватывающий данный метод.
3). Каким образом можно правильно организовать вызов данного метода, т.е. method.invoke(...) из прокси-класса?
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175469
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13,

Код: java
1.
return -method.invoke(args[0],target); 
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175483
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13Где можно посмотреть пример правильной реализации делегирования?


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
for(int i = 0; i < args.length; i++){
   Object arg = args[i];
   if(arg != null && Proxy.isProxyClass(arg.getClass()){
      TraceHandler handler = (TraceHandler) Proxy.getInvocationHandler(arg);     
      args[i] = handler.target;
   }
}

return method.invoke(target, args);  
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175485
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
0FDll13,

Код: java
1.
return -method.invoke(args[0],target); 


Зачетный трюк.
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175487
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13Подводя итог по данному вопросу:
1). Есть интерфейс Comparable(содержит один метод compareTo)
2). Есть класс Integer, реализующий данный интерфейс.
3). Есть прокси-класс, перехватывающий данный метод.
3). Каким образом можно правильно организовать вызов данного метода, т.е. method.invoke(...) из прокси-класса?

Проблема в аргументе. Это понятно?
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175488
ll13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0FDll13,

Код: java
1.
return -method.invoke(args[0],target); 



Ошибка:
Uncompilable source code - bad operand type java.lang.Object for unary operator '---'

Даже если бы это сработало, проблемы это не решает. Это всего лишь пример, с помощью которого я пытаюсь понять как работает этот механизм.
А если у интерфейса будет 1000 методов... то для каждого персональные условия для invoke писать ?! Более того интерфейсы которые требуется перехватывать могут определяться в процессе работы программы и неизвестны на этапе компиляции.
Тогда какой смысл в прокси?
Насколько я понял, динамические прокси-классы нужны для того, что бы перехватить обращение к методам заранее неизвестного интерфейса(ов), выполнить некие дополнительные действия, например логирование, как в данном примере, а затем вызвать требуемый метод объекта.
Или я чего-то недопонимаю....?
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175494
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13,

Ну конечно, возвращается Integer. -((Integer)m.invoke).intValue()
У method есть имя getName(), обрабатываете только нужные, например if(method.getName().equals("compareTo")), остальные method.invoke(...)
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175496
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13Ошибка:
Uncompilable source code - bad operand type java.lang.Object for unary operator '---'

Вы слишком рано задаёте вопросы про прокси, если банально ещё ни синтаксис не освоили, ни вообще не понимаете код в примере из книги.

ll13Даже если бы это сработало, проблемы это не решает. Это всего лишь пример, с помощью которого я пытаюсь понять как работает этот механизм.

минус уберите и сработает.

ll13А если у интерфейса будет 1000 методов... то для каждого персональные условия для invoke писать ?! Более того интерфейсы которые требуется перехватывать могут определяться в процессе работы программы и неизвестны на этапе компиляции.

Ну, просто здесь такой вот особый пример. Проблема не в прокси, а в том что у вас массив прокси. И если вы создаёте массив прокси и пытаетесь сравнивать прокси с прокси, вы должны понимать последствия.
Конечно, отчасти это ещё и связано с реализацией именно Java Proxy. Существуют другие способы создать прокси. У них подобной проблемы не будет.

ll13Тогда какой смысл в прокси?

Есть такой термин - Aspect-Oriented Programming.

ll13Насколько я понял, динамические прокси-классы нужны для того, что бы перехватить обращение к методам

Угу.

ll13заранее неизвестного интерфейса(ов),

Смешно, да. В методе Proxy.newProxyInstance() где там неизвестные интерфейсы?

ll13выполнить некие дополнительные действия, например логирование, как в данном примере, а затем вызвать требуемый метод объекта. Или я чего-то недопонимаю....?
Всё верно. Задумка такая. Но есть теория, а есть практика. И практика зачастую накладывает ряд ограничений. Это надо понимать.
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175536
ll13
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо! это рабочий код, буду разбираться дальше.

Blazkowicz
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
for(int i = 0; i < args.length; i++){
   Object arg = args[i];
   if(arg != null && Proxy.isProxyClass(arg.getClass()){
      TraceHandler handler = (TraceHandler) Proxy.getInvocationHandler(arg);     
      args[i] = handler.target;
   }
}

return method.invoke(target, args);  



BlazkowiczСмешно, да. В методе Proxy.newProxyInstance() где там неизвестные интерфейсы?

Ну например можно так:
Код: java
1.
Object proxy = Proxy.newProxyInstance(null , Class.forName("НеизвестныйЗаранееКласс").getInterfaces(), handler);
...
Рейтинг: 0 / 0
Вопрос по proxy-классам.
    #39175561
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ll13Ну например можно так:
Код: java
1.
Object proxy = Proxy.newProxyInstance(null , Class.forName("НеизвестныйЗаранееКласс").getInterfaces(), handler);



:) В общем, для логирования и подобных AOP решений, JDK Proxy никто не использует. Он подходит только для каких-то простых реализаций, чтобы сделать фасад и перехватывать вызовы к определенному интерфейсу.

Более глобальные вещи реализуют через AOP библиотеки типа Aspect4j.
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Вопрос по proxy-классам.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]