之前写过一个静态代理的代理模式,这次基于JAVA实现一个动态代理。
Java动态代理涉及到反射的相关知识,Proxy,Method。在java.reflect.*包下。要实现动态代理需要代理类实现一个动态代理的接口InvocationHandler。
首先实现InvocationHandler,最好代理实现的接口。这里试着代理一个Runnable接口,代理类的实现如下代码
public class WeakHandler<T extends Runnable> implements InvocationHandler{
WeakReference<T> weakReference ;
//这里是代理类我们使用了一个弱引用来保存了引用的实体。
public WeakHandler(T object) {
super();
weakReference = new WeakReference<T>(object);//①
}
//接口方法,主要参考第二个和第三个,method是被代理的方法,args是方法的参数
//方法中使用method.invoke来驱动对象执行它的方法。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
T object = weakReference.get();//①
return object==null? null : method.invoke(object, args);
}
//生成代理类的回调,之后使用这个返回对象来执行主体的方法
private static Runnable wrap(Runnable target) {
System.out.println("我是 WeakInvocationHandle");
return (Runnable)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new WeakHandler<Runnable>(target));//②
}
public static Runnable warp(IHost<Runnable> host,Runnable target) {
if (host!=null && target!=null) {//宿主记录下代理的列表
host.referObject(target);//③
}
return wrap(target);
}
static interface IHost<T>{//宿主实现的接口
void referObject(T args);
}
}
上方主要是实现了对一个接口代理的封装,有兴趣可以做泛型,支持更多的接口。注释①处是对弱引用的使用,减少内存泄漏。②是关联代理类和被代理类的地方,Proxy关联两者。③将在被代理的类传递给宿主的地方。
调用的地方如下,没有多线程存在,Runnable直接调用了run(),
public class InvocationHandlerDemo implements IHost<Runnable>{
private List<Runnable> refreList = new ArrayList<>();
private int xx =13;
private void init() {
Runnable runnable = WeakHandler.warp(this, new Runnable() {
@Override
public void run() {
System.out.println("我是 runnable"+xx);
refreList.clear();
}
});
runnable.run();
System.out.println("被代理的还有"+refreList.size()+"个");
}
public static final void main(String[] args) {
new InvocationHandlerDemo().init();
}
public void referObject(Runnable args) {
refreList.add(args);
};
}