利用InvocationHandler接口和Proxy类的静态方法我们可以实现对任何一个接口对象的动态代理(类似于wrapper,就是通过对proxy的调用实现对真正要调用对象的操作):
InvocationHandler接口:
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
Proxy.newProxyInstance方法:
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
譬如,对于MyInterface接口:
public interface MyInterface {
void doSomething ();
}
我们可以通过自己实现一个InvocationHandler接口(MyInvocationHandler),然后通过Proxy.newProxyInstance方法返回一个MyInterface类的动态代理(这个代理实现了MyInterface的所有方法,但是这个代理不是一个MyInterface对象,它就是一个代理而已,一个动态创建的类,通过调用这个代理的方法实现调用MyInterface的方法)。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class MyInvocationHandler implements InvocationHandler {
@Override
public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
Arrays.stream(Thread.currentThread()
.getStackTrace())
.forEach(System.out::println);
System.out.println(method);
System.out.println("the invoked method: " + method);
return null;
}
public static void main (String[] args) {
MyInvocationHandler handler = new MyInvocationHandler();
MyInterface o = (MyInterface) Proxy.newProxyInstance(
MyInvocationHandler.class.getClassLoader(),
new Class[]{MyInterface.class}, handler);
o.doSomething();
}
}
在上述代码中,调用代理o的doSomething方法时,代理o会调用handler的invoke方法,并且分别将invoke的参数Object proxy设置为代理o、参数Method method设置为doSomething方法、Object[] args设置为调用doSomething时使用的参数。
动态代理的作用
实现指定类的wrapper,拦截对该类的方法调用:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInterceptor<T> implements InvocationHandler {
private T t;
public MyInterceptor(T t) {
this.t = t;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method call : " + method.getName());
Object result = method.invoke(t, args);
System.out.println("after method call : " + method.getName());
return result;
}
@SuppressWarnings("unchecked")
public static <T> T getProxy(T t, Class<? super T> interfaceType) {
MyInterceptor handler = new MyInterceptor(t);
return (T) Proxy.newProxyInstance(interfaceType.getClassLoader(),
new Class<?>[]{interfaceType}, handler
);
}
}
对于Javabean类型的类实现带cache的decorator
public interface IObject {
String getData ();
}
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
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());
}
}
近期评论