Это основано на вашем ответе на мой комментарий.
Вы действительно можете использовать MyCustomInterface
и ваш proxyClass для создания своего рода миксина на Java. Но вам все равно придется преобразовать прокси-класс в MyCustomInterface
, чтобы иметь возможность вызывать методы.
Давайте начнем.
Создание вашего прокси
Сначала вы создаете свой прокси, что вы уже делали:
// this is the code you've already posted
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(entity.getClass());
factory.setInterfaces(new Class[] { MyCustomInterface.class });
Обработчик метода: творит чудеса
Прокси-серверы Javassist позволяют добавлять MethodHandler. По сути, он имеет InvocationHandler в обычном прокси-сервере Java, что означает, что он работает как перехватчик метода.
Обработчик метода будет вашим миксином! Сначала вы создаете новый MethodHandler с настраиваемым полем, которое вы действительно хотите добавить в класс, вместе с объектом сущности, который вы начали проксировать:
public class CustomMethodHandler implements MethodHandler {
private MyEntity objectBeingProxied;
private MyFieldType myCustomField;
public CustomMethodHandler(MyEntity entity) {
this.objectBeingProxied = entity;
}
// code here with the implementation of MyCustomInterface
// handling the entity and your customField
public Object invoke(Object self, Method method, Method proceed, Object[] args) throws Throwable {
String methodName = method.getName();
if(methodNameFromMyCustomInterface(methodName)) {
// handle methodCall internally:
// you can either do it by reflection
// or if needed if/then/else to dispatch
// to the correct method (*)
}else {
// it's just a method from entity let them
// go. Notice we're using proceed not method!
proceed.invoke(objectBeingProxied,args);
}
}
}
(*) Обратите внимание, что даже если я скажу в комментарии для внутренней обработки вызова, вы можете разместить реализацию интерфейса в другом месте, которое не является обработчиком вашего метода, и просто вызвать его отсюда.
Собираем все вместе
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(entity.getClass());
factory.setInterfaces(new Class[] { MyCustomInterface.class });
Class cls = factory.createClass();
// bind your newly methodHandler to your proxy
((javassist.util.proxy.Proxy) cls).setHandler(new CustomMethodHandler(entity));
EntityClass proxyEntity = cls.newInstance();
Теперь у вас должна быть возможность делать ((MyCustomInterface)proxyEntity).someMethodFromTheInterface()
, и пусть этим занимается ваш CustomMethodHandler
Подводя итоги
- Вы создаете прокси с помощью Proxy Factory из javassist
- Вы создаете свой собственный класс MethodHandler, который может получать вашу проксируемую сущность и поле, с которым вы хотите работать.
- Вы привязываете methodHandler к своему прокси, чтобы вы могли делегировать реализацию интерфейса
Имейте в виду, что этот подход не идеален, поскольку это один из недостатков: код в классе Entity не может ссылаться на интерфейс, если вы сначала не создадите прокси.
Если вам что-то не совсем понятно, просто прокомментируйте, и я постараюсь уточнить вас.
person
pabrantes
schedule
12.12.2013