По документации :
[
java.lang.reflect.
]Proxy
предоставляет статические методы для создания динамических прокси-классов и экземпляров, а также является суперклассом всех динамических прокси-классов, созданных этими методами.
newProxyMethod
Метод (отвечает за генерацию динамических прокси) имеет следующую подпись:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
К сожалению, это не позволяет генерировать динамический прокси, который расширяет определенный абстрактный класс (а не реализует определенные интерфейсы). Это имеет смысл, учитывая, что java.lang.reflect.Proxy
это «суперкласс всех динамических прокси», тем самым предотвращая то, что другой класс является суперклассом.
Следовательно, есть ли какие-либо альтернативы тому, java.lang.reflect.Proxy
что может генерировать динамические прокси, которые наследуются от определенного абстрактного класса, перенаправляя все вызовы абстрактных методов на обработчик вызова?
Например, предположим, что у меня есть абстрактный класс Dog
:
public abstract class Dog {
public void bark() {
System.out.println("Woof!");
}
public abstract void fetch();
}
Есть ли класс, который позволяет мне делать следующее?
Dog dog = SomeOtherProxy.newProxyInstance(classLoader, Dog.class, h);
dog.fetch(); // Will be handled by the invocation handler
dog.bark(); // Will NOT be handled by the invocation handler
источник
proxyFactory.setHandler()
не рекомендуется. Пожалуйста, используйтеproxy.setHandler
.Что вы можете сделать в таком случае, так это иметь обработчик прокси, который будет перенаправлять вызовы к существующим методам вашего абстрактного класса.
Вам, конечно, придется его закодировать, но это довольно просто. Для создания вашего прокси вам нужно предоставить ему
InvocationHandler
. После этого вам нужно будет только проверить тип метода вinvoke(..)
методе вашего обработчика вызова. Но будьте осторожны: вам придется проверять тип метода по базовому объекту, связанному с вашим обработчиком, а не по объявленному типу вашего абстрактного класса.Если я возьму в качестве примера ваш класс собаки, метод invoke вашего обработчика вызовов может выглядеть следующим образом (с существующим связанным подклассом собаки, который называется ... ну ...
dog
)public void invoke(Object proxy, Method method, Object[] args) { if(!Modifier.isAbstract(method.getModifiers())) { method.invoke(dog, args); // with the correct exception handling } else { // what can we do with abstract methods ? } }
Однако есть кое-что, что заставляет меня задуматься: я говорил об
dog
объекте. Но поскольку класс Dog является абстрактным, вы не можете создавать экземпляры, поэтому у вас есть существующие подклассы. Более того, как показывает тщательная проверка исходного кода прокси, вы можете обнаружить (на Proxy.java:362), что невозможно создать прокси для объекта класса, который не представляет интерфейс).Итак, помимо реальности , то, что вы хотите делать, вполне возможно.
источник
Dog
(например, я явно не пишуPoodle
класс, который реализуетfetch()
). Следовательно, нетdog
переменной для вызова методов ... Извините, если я запутался, мне придется подумать над этим еще немного.java.lang.reflect.Proxy
), который делает то, что мне нужно.