Как правильно сгенерировать динамический прокси-класс, основанный на правильном классе?
У меня есть интерфейс, определенный следующим образом:
public interface Cache {
}
Затем абстрактный класс, реализующий вышеупомянутое:
public abstract class AbstractCache implements Cache {
}
Затем конкретный класс, наследующий сверху:
public class RealTimeCache extends AbstractCache {
}
Затем другой класс определяется следующим образом:
public class CacheProbe {
public static <T> T probe(T base) {
return (T) Proxy.newProxyInstance(
base.getClass().getClassLoader(),
new Class[]{Cache.class},
new MethodCountInvocationHandler(base) // I am not mentioning this class as it's irrelevant
);
}
}
У меня есть следующий класс, который использует все вышеперечисленное:
public class CacheLoader<T extends Cache> {
public T load() {
T result = getResult(...);
CacheProbe x = new CacheProbe(result);
return x.probe();
}
}
Наконец, строки, вызывающие проблему (расположены вне классов):
final CacheLoader<RealTimeCache> cacheLoader = getNewLoader(); //Method of this method is irrelevant and unchangeable
RealTimeCache x = cacheLoader.load(); //This is the line which is causing a runtime issue
Проблема в том, что во время выполнения в последнюю строку, упомянутую выше, выдается следующее исключение:
java.lang.ClassCastException: com.sun.proxy.$Proxy57 cannot be cast to RealTimeCache
Однако я не вижу, как это возможно, потому что динамический прокси-класс сгенерирован на основе Cache
,
Как это исправить?
Обратите внимание, что я могу только изменить CacheProbe
класс, чтобы исправить это. Cache
, AbstractCache
, RealTimeCache
, CacheLoader
и эти последние две строки неизменны.
1 ответ
Однако я не вижу, как это возможно, потому что динамический прокси-класс сгенерирован на основе
Cache
,
Да, документы для java.lang.reflect.Proxy
сказать
Proxy
предоставляет статические методы для создания динамических прокси-классов и экземпляров, а также является суперклассом всех динамических прокси-классов, создаваемых этими методами.
(выделение добавлено)
Таким образом, вы не можете использовать Proxy
создать (экземпляр) подкласс произвольного класса по вашему выбору.
Как это исправить?
Вы можете создать обычный подкласс RealTimeCache
и вернуть экземпляр этого. Proxy
предназначен в первую очередь для обслуживания интерфейсов, которые не известны до времени выполнения, и в этом случае единственным способом взаимодействия с ними в любом случае является тип интерфейса. Это не твой сценарий.
При необходимости вы можете реализовать такой подкласс с точки зрения MethodCountInvocationHandler
так же, как использует ваш прокси-класс, но я уверен, что будет проще реализовать любой инструментарий, который предполагается предоставить напрямую.