Jeśli masz interfejsy deklarujące metody, do których chcesz rejestrować połączenia, możesz użyć standardowego interfejsu API Proxy, aby osiągnąć to, co chcesz.
Proxy API pozwoliłoby na owinięcie rzeczywistej implementacji w nową klasę proxy, która rejestrowałaby połączenie i przekazywanie wywołania do implementacji. Trzeba tylko zaimplementować jeden InvocationHandler
, który wykonuje rejestrowanie i przekazywanie.
Na przykład
interface Calculator {
int add(int a, int b);
}
class CalculatorImpl implements Calculator {
@Override public int add(int a, int b) { return a+b; }
}
class LoggingInvocationHandler implements InvocationHandler {
private final Object delegate;
public LoggingInvocationHandler(final Object delegate) {
this.delegate = delegate;
}
@Override invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method: " + method + ", args: " + args);
return method.invoke(delegate, args);
}
}
class X {
public static void main(String... args) {
final Calculator calc = new CalculatorImpl();
final Calculator loggingCalc =
(Calculator) Proxy.newProxyInstance(X.class.getClassLoader(),
new Class[] {Calculator.class},
new LoggingInvocationHandler (calc));
loggingCalc.add(2, 3); // shall print to the screen
}
}
Można również łatwo zalogować wartości zwracanych i wyjątki generowane przez metod, tylko przez zmianę kodu w InvocationHandler
. Można również użyć dowolnej struktury rejestrowania, zamiast wersji System.out.println
, jak w przykładzie.
Aby zalogować wartości i wyjątki powrotne, można zrobić coś takiego:
@Override invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("method: " + method + ", args: " + args);
try {
final Object ret = method.invoke(delegate, args);
System.out.println("return: " + ret);
return ret;
} catch (Throwable t) {
System.out.println("thrown: " + t);
throw t;
}
}
AOP może warto spróbować. – Nishant