Implementing Decorator pattern using JDK dynamic proxy.

public class GenericCacheDecorator implements InvocationHandler {
private Map<String, Object> cachedData = new HashMap<>();
private Object EMPTY = new Object();
private Object obj;
private GenericCacheDecorator (Object obj) {
this.obj = obj;
try {
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
for (PropertyDescriptor desc : beanInfo.getPropertyDescriptors()) {
cachedData.put(desc.getReadMethod()
.getName(), EMPTY);
}
} catch (IntrospectionException e) {
e.printStackTrace();
}
}
public static <I, T extends I> I decorate (T t, Class<I> interfaceClass) {
GenericCacheDecorator cacheableDecorator = new GenericCacheDecorator(t);
return (I) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
new Class[]{interfaceClass}, cacheableDecorator);
}
public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
if (cachedData.containsKey(method.getName())) {
Object o = cachedData.get(method.getName());
if (o == EMPTY) {
Object returned = method.invoke(obj, args);
cachedData.put(method.getName(), returned);
return returned;
} else {
return o;
}
}
return method.invoke(args);
}
public static void main (String[] args) {
MyObject object = new MyObject();
IObject iObject = GenericCacheDecorator.decorate(object, IObject.class);
System.out.println(iObject.getData());
System.out.println(iObject.getData());
}
}
Original Post