Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Implementing a method wrapper (using java.lang.reflect.Proxy)
package com.inalgebra.proxytest;
import com.inalgebra.proxy.MethodWrapper;
import java.lang.reflect.Method;
/**
* Created with IntelliJ IDEA.
* User: synther
* Date: 7/22/12
* Time: 7:00 PM
*/
class Worker implements WorkerInterface {
public String makeWithResult() {
System.out.println("Worker.makeWithResult()");
return "RESULT";
}
@Override
public void make() {
System.out.println("Worker.make()");
}
}
public class Program {
public static void main(String[] args) {
Worker worker = new Worker();
// Оборачиваем
WorkerInterface wrappedWorker = (WorkerInterface) new MethodWrapper(worker) {
@Override
protected void handleMethod(Method method, Object[] args) throws Throwable {
System.out.println("@before");
invoke();
System.out.println("@after\n");
}
}.wrap();
// Вызываем методы
wrappedWorker.make();
String result = wrappedWorker.makeWithResult();
System.out.println("print " + result);
}
}
@before
Worker.make()
@after
@before
Worker.makeWithResult()
@after
print RESULT
Process finished with exit code 0
package com.inalgebra.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Non thread safe.
*
* User: synther
* Date: 7/22/12
* Time: 9:51 PM
*/
public abstract class MethodWrapper {
/**
* Объект, методы которого оборачиваются
*/
private final Object wrapped;
/**
* Метод, который вызывается в данный момент
*/
private Method method;
/**
* Аргументы с которыми вызывается метод в данный момент
*/
private Object[] args;
/**
* Результат метода который вызывается в текущий момент
*/
private Object result;
/**
* @param wrapped объект, методы которого нужно обернуть методом
* {@link #handleMethod(java.lang.reflect.Method, Object[])}
*/
public MethodWrapper(Object wrapped) {
this.wrapped = wrapped;
}
/**
* @return возвращает объект с обернутыми методами, который можно привести
* к любому интерфейсу и использовать
*/
public Object wrap() {
return Proxy.newProxyInstance(
wrapped.getClass().getClassLoader(),
wrapped.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodWrapper.this.method = method;
MethodWrapper.this.args = args;
MethodWrapper.this.handleMethod(method, args);
MethodWrapper.this.method = null;
MethodWrapper.this.args = null;
return result;
}
}
);
}
/**
* Метод, который наследник заменяет для перехвата методов.
* В реализации нужно вызвать {@link #invoke()} (или перегруженный метод).
*
* @param method
* @param args
* @throws Throwable
*/
protected abstract void handleMethod(Method method, Object[] args) throws Throwable;
/**
* Выполняет метод оригинального объекта (который оборачиваем).
* Вызывать нужно из {@link #handleMethod(java.lang.reflect.Method, Object[])}
*
* @param method
* @param args
* @return результат метода, который оборачиваем
* @throws Throwable
*/
protected final Object invoke(Method method, Object[] args) throws Throwable {
if (method == null) {
throw new IllegalStateException("Invoke from handleMethod(...) only");
}
try {
return result = method.invoke(wrapped, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
/**
* Выполняет метод оригинального объекта (который оборачиваем).
* Вызывать нужно из {@link #handleMethod(java.lang.reflect.Method, Object[])}
*
* @throws Throwable
*/
public final void invoke() throws Throwable {
invoke(method, args);
}
}
package com.inalgebra.proxytest;
/**
* Created with IntelliJ IDEA.
* User: synther
* Date: 7/22/12
* Time: 7:00 PM
*/
public interface WorkerInterface {
String makeWithResult();
void make();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.