Как правильно сгенерировать динамический прокси-класс, основанный на правильном классе?

У меня есть интерфейс, определенный следующим образом:

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так же, как использует ваш прокси-класс, но я уверен, что будет проще реализовать любой инструментарий, который предполагается предоставить напрямую.

Другие вопросы по тегам