Goeienacht,
Hieronder een typisch voorbeeld van het Proxy design pattern, maar dan met behulp van dynamic proxies. In het kort: de interface is Dao, de implementatie van die interface is DaoImpl, de dynamic proxy en de InvocationHandler CachingHandler onderscheppen calls naar de implementatie.
Tot zover alles okee, en het onderstaande werkt. Wat niet werkt, is de proxy instance uitprinten in de invoke() method van de InvocationHandler, dan krijg je namelijk een StackOverflowError. Bij nader inzien redelijk logisch: in invoke() onderschept de proxy opnieuw de call naar de implementatie, en komt weer in de invoke() method terecht, en opnieuw, en opnieuw, en opnieuw.
proxy.getClass() doen zoals hieronder werkt dus wel. Vraag: waarom wordt toString() onderschept en getClass() niet?
Code:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Dao {
void insert();
void get();
void update();
void delete();
}
class DaoImpl implements Dao {
public void insert() { System.out.println(this.getClass().getName() + ".insert()"); }
public void get() { System.out.println(this.getClass().getName() + ".get()"); }
public void update() { System.out.println(this.getClass().getName() + ".update()"); }
public void delete() { System.out.println(this.getClass().getName() + ".delete()"); }
}
class CachingHandler implements InvocationHandler {
private final Dao dao;
public CachingHandler(Dao dao) {
this.dao = dao;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// StackOverflowError
// System.out.println(proxy);
System.out.println(proxy.getClass().getName() + " intercepted " + method);
return method.invoke(dao, args);
}
}
public class DynamicProxy {
public static void f(Dao dao) {
dao.insert();
dao.get();
dao.update();
dao.delete();
}
public static void main(String[] args) {
Dao dao = new DaoImpl();
f(dao);
Dao proxy = (Dao)Proxy.newProxyInstance(dao.getClass().getClassLoader(),
new Class<?>[] { Dao.class },
new CachingHandler(dao));
f(proxy);
}
}
Output:
Code:
DaoImpl.insert()
DaoImpl.get()
DaoImpl.update()
DaoImpl.delete()
$Proxy0 intercepted public abstract void Dao.insert()
DaoImpl.insert()
$Proxy0 intercepted public abstract void Dao.get()
DaoImpl.get()
$Proxy0 intercepted public abstract void Dao.update()
DaoImpl.update()
$Proxy0 intercepted public abstract void Dao.delete()
DaoImpl.delete()