什么是代理模式
假如我喜欢上隔壁班的翠花,但是我没胆量向她送花,这时候我需要一个铁杆哥们帮我做这件事, 很明显这哥们是个代理,是去执行任务的,但是花实际上是我“送”的,代理和我一样会送花这个动作,直接上代码。
1 public interface IProcess { 2 void SendFlower(); 3 }
1 public class Studnet1 implements IProcess { 2 3 @Override 4 public void SendFlower() { 5 System.out.println("my name is Studnet1 , the flower is for you "); 6 } 7 } 8 9 10 11 12 13 public class ProxyStudent implements IProcess { 14 15 private IProcess targetObj; 16 17 public ProxyStudent(IProcess targetObj) { 18 this.targetObj = targetObj; 19 } 20 21 @Override 22 public void SendFlower() { 23 System.out.println("check it before send"); 24 targetObj.SendFlower(); 25 System.out.println("check it after send"); 26 } 27 } 28
1 public class ProcessFactory { 2 public static IProcess getProcess(){ 3 return new Studnet1(); 4 } 5 } 6
1 public class Main { 2 3 public static void main(String[] args) { 4 IProcess ProxyObj = ProcessFactory.getProcess(); 5 ProxyObj.SendFlower(); 6 } 7 }
运行结果:
1 check it before send 2 my name is Studnet1 , the flower is for you 3 check it after send
很开心,终于把花送出去了,可以见到调用代理者的SendFlower方法,实际上是我的SendFlower 方法,打到我需要送花的目的,同时这铁哥们人缘非常好,其他的同学也需要他来帮忙 , Student2, Student3 , Student4 也需要这铁哥们,
并且他们的要求不只是送花,还可能邀请看电影….等等,那么ProcessFatory 也要改写,另外假如我不止想送花这个动作,需要添加方法到接口上,那么其他类相应的也要改动。
1 public class ProcessFactory { 2 public static IProcess getProcess(){ 3 return new Studnet1(); 4 } 5 6 public static IHold getHold(){ 7 return new Studnet2(); 8 } 9 10 public static IMovie getMovier(){ 11 return new Studnet3(); 12 } 13 14 ..... 15 16 }
显然这样的每次一个新的一个需求都需要创建一个对象,很不合理,于是就出现了动态代理。
动态代理
先上代码,新建一个类,
1 public class StuInvocationHandler<T> implements InvocationHandler { 2 T target; 3 4 public StuInvocationHandler(T target) { 5 this.target = target; 6 } 7 8 9 @Override 10 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 11 System.out.println("this is a proxy method"); 12 System.out.println("check it before sending"); 13 Object result = method.invoke(target, args); 14 System.out.println("check it after sending "); 15 return result; 16 } 17 }
调用,输出结果:
1 public class Main { 2 3 public static void main(String[] args) { 4 IProcess student1 = ProcessFactory.getProcess(); 5 InvocationHandler handler = new StuInvocationHandler<IProcess>(student1); 6 IProcess ProxyStudent = (IProcess) Proxy.newProxyInstance(IProcess.class.getClassLoader(), new Class<?>[]{IProcess.class}, handler); 7 ProxyStudent.SendFlower(); 8 9 } 10 }
1 this is a proxy method 2 check it before sending 3 my name is Studnet1 , the flower is for you 4 check it after sending
我们似乎看不到了代理类,实际上StuInvocationHandler就是我们的代理类,这时无论代理谁都可以进行操作,动态代理运用了java一个重要的特性—“反射” 。 可以查看这篇文章,http://https://www.cnblogs.com/gonjan-blog/p/6685611.html。 我们需要知道两点:
- 代理类调用方法使用了反射
- 代理类继承了Proxy , 实现了被代理的接口,对应例子中的 IProcess , 由于java是单继承,所以也就决定了java动态代理只能对接口进行代理。
再回想一下,调用invoke方法前后我们都是可以进行其他操作的,实际上这就是Spring里的AOP,Spring的AOP实现其实也是用了Proxy和InvocationHandler这两个东西的。