Java генерирует прокси-класс для данного интерфейса и обеспечивает экземпляр прокси-класса. Но когда мы вводим, бросает объект прокси к нашему конкретному объекту, как Java обрабатывает это внутренне? Это рассматривают как специальный сценарий?
Например, у меня есть класс OriginalClass
и это реализует OriginalInterface
, когда я создаю объект прокси путем передачи OriginalInterface
интерфейс Java создал прокси-класс ProxyClass
использование методов в обеспеченном интерфейсе и обеспечивает объект этого класса (т.е. ProxyClass
). Если мое понимание корректно, затем может Вы отвечать на следующие запросы
ProxyClass
к моему классу OriginalClass
это работает, но как Java позволяет это? То же в случае instace?Спасибо, студент
Java не позволяет приводить от прокси к конкретному классу. Прокси в JDK (java.lang.reflect.Proxy
) являются только прокси интерфейса. Полученный прокси имеет тип ProxyX
(X - число), и если вы попытаетесь привести его к любому классу, то получите ClassCastException
Поэтому ваши 2-й и 3-й вопросы не актуальны - прокси не подкреплен конкретным классом. Для этого можно использовать другие механизмы проксирования - CGLIB или javassist. Они используют динамический подкласс, и поэтому все защищенные
(и выше) поля и методы доступны подклассу (прокси).
Из документации javadocs API для java.lang.reflect. InvocationHandler:
InvocationHandler - это интерфейс, реализованный обработчиком вызова экземпляра прокси.
Динамический прокси реализует интерфейс, но использует обработчик (OriginalClass) для предоставления базовых реализаций методов.
Чтобы ответить на ваши вопросы:
Внутри реализации динамического прокси (например, в реализации метода invoke (...)) вы можете получить доступ к членам обработчика, используя отражение.
Вот тестовый код, который я использовал для проверки своего ответа:
// package ...;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import junit.framework.Assert;
import org.junit.Test;
public class TestDynamicProxy
{
@Test
public void testCast() throws Exception {
Foo foo = (Foo) TestProxy.newInstance(new FooImpl());
foo.bar(null);
System.out.println("Class: " + foo.getClass());
System.out.println("Interfaces: " + foo.getClass().getInterfaces());
Assert.assertNotNull(foo);
Assert.assertTrue(foo instanceof Foo);
Assert.assertFalse(foo instanceof FooImpl);
}
}
interface Foo
{
Object bar(Object obj) throws Exception;
}
class FooImpl implements Foo
{
public Object bar(Object obj) throws Exception {
return null;
}
}
class TestProxy implements java.lang.reflect.InvocationHandler
{
private final Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new TestProxy(obj));
}
private TestProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result;
try {
result = m.invoke(obj, args);
}
catch (InvocationTargetException e) {
throw e.getTargetException();
}
catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
Эта статья содержит много полезной информации и примеров кода.