对于代理模式,分为静态代理与动态代理,虽然静态代理有诸多好处,但是有一点:代码量翻倍就不好了,因此当我们需要代理大量对象的时候,静态代理显然不能再使用了,为了适应这种情况,衍生出动态代理。
动态代理实现方式又有:1.jdk-Proxy与InvocationHandler 2.cglib 3.javasist等等。
本节我们以jdk中的动态代理从一步步使用到推到成一个万能模板,OK let's start!
ps:如果大家不想知道太多我怎么一步步演化过去,只想用我写的最终的万能模板动态代理代码的话,ok,拉到最下面!
====
假如现在有一个人想租房东(Host)的房子,但是房东他找不到,他只能通过中介来租房子,OK以这个例子来描绘动态代理。
====
ps:我们实现动态代理,被代理的对象必须有接口,这个想必有点设计模式的人都有这种思想,OK,提一下!
房东租房子的接口:
public interface Rent { void rent(); }
具体的房东:
public class Host implements Rent { public void rent() { System.out.println("房东出租房子!"); } }
//初步的动态代理类:
public class ProxyInvocationHandler implements InvocationHandler { private Rent rent; public void setRent(Rent rent) { this.rent = rent; } public Object getProxyClass(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(rent,args); } }
调用:
public static void main(String[] args) { ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();//动态代理类 proxyInvocationHandler.setObj(new Host());//需要代理的对象 Rent proxyClass = (Rent) proxyInvocationHandler.getProxyClass();//创建并获取代理对象 proxyClass.rent();//代理对象方法调用 }
上方的这些代码,看起来是没什么问题哈,动态代理的功能也确实实现了,但是呢?有两个问题:
1.动态代理的对象写死为Rent,这个动态代理对象无法代理除Rent以外的对象
2.代理对象一般都需要增强一些功能的添加,这里如果增加的话,直接在ProxyInvocationHandler增加,这岂不是违反了开闭原则,根本无法封装
为了解决上面的两个问题,OK我们来逐个分析:
1.我们可以将Rent对象变为Object就解决了,OK这个没问题
2.方法不能写死,那么怎么办呢?使用模板方法的思想,我们将方法的实现抽离出来,将方法的动作保留,同时考虑到可能没有这个动作,因此:有这个动作,我们就做这个动作,如果没有这个动作,那么就不做这个动作(很简单判断对象是否为null就好啦)。
OK,分析的很合理,let's write code:
public class ProxyInvocationHandler implements InvocationHandler { //设置代理类 private Object obj; private preFunc pre; private endFunc end; public void setObj(Object _obj) { this.obj = _obj; } public void setObj(Object _obj, preFunc pre, endFunc end) { this.obj = _obj; this.pre = pre; this.end = end; } //获取代理对象 public Object getProxyClass() { return Proxy.newProxyInstance(this.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } //处理代理示例,并返回结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(pre!=null)pre.doSomething(); //动态代理的本质就是使用反射 Object result = method.invoke(obj, args); if(end!=null)end.doSomething(); return result; } public interface preFunc { void doSomething(); } public interface endFunc { void doSomething(); } }
如何调用处理代码呢?
public static void main(String[] args) { ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();//动态代理类 proxyInvocationHandler.setObj(new Host(), new ProxyInvocationHandler.preFunc() { @Override public void doSomething() { System.out.println("中介者dosomethingBefore"); } }, new ProxyInvocationHandler.endFunc() { @Override public void doSomething() { System.out.println("中介者dosomethingAfter"); } });//需要代理的对象 Rent proxyClass = (Rent) proxyInvocationHandler.getProxyClass();//创建并获取代理对象 proxyClass.rent();//代理对象方法调用 }
perfect,搞定!
每天努力一点点,继续加油哦~~