Created
July 22, 2012 19:14
-
-
Save synther/3160753 to your computer and use it in GitHub Desktop.
Implementing a method wrapper (using java.lang.reflect.Proxy)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@before | |
Worker.make() | |
@after | |
@before | |
Worker.makeWithResult() | |
@after | |
print RESULT | |
Process finished with exit code 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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