代理模式
1、什么叫代理模式
官方解释:
(1) 为其他对象提供一种代理。以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
(2) 对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。
(3) 代理模式最主要的就是有一个公共接口,一个具体的类,一个代理类,代理类持有具体类的实例,代为执行具体类实例方法。代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。这里的间接性就是指不直接调用实际对象的方法,那么我们在代理过程中就可以加上一些其他用途。
通俗解释:A要做某件事,但是A临时别其他事情耽搁没时间,B代替A去做这件事。
2、什么叫动态代理,什么叫静态代理
动态代理:代理类在程序运行时创建的代理方式被成为动态代理。
静态代理:程序未运行前,编译阶段就已经创建好的代理类,这种代理为静态代理。
3、静态代理样例
---- 我们以xiaojiang (被代理者)做完作业,xiaozhou(代理者) 作为班长,老师让xiaozhou代交,避免每个学生都要跑一趟浪费学习时间,以此为例写一个简单的静态代理样例
//交作业的接口 public interface Homework { void handHomework (); }
//xiaojiang需要交作业 public class XiaoJiang implements Homework { private String name; public XiaoJiang(String name) { this.name = name; } @Override public void handHomework() { System.out.println(name+"来交作业啦"); } }
//xiaozhou 虽然为班长但是也要交作业 public class XiaoZhou implements Homework { private XiaoJiang xiaoJiang; public XiaoZhou(Homework xiaoJiang) { this.xiaoJiang = (XiaoJiang) xiaoJiang; } @Override public void handHomework() { xiaoJiang.handHomework(); } }
//我们调用xiaozhou交作业的方法 public static void main(String[] args) { XiaoJiang xiaoJiang = new XiaoJiang("xiaojiang"); XiaoZhou xiaoZhou = new XiaoZhou(xiaoJiang); xiaoZhou.handHomework(); }
main运行完后控制台输出是: xiaojiang来交作业啦
注意到没有,我们main方法里,交作业的发起人是xiaozhou 而不是xiaojiang,这就是静态代理。最终是代理者替被代理者执行了某事
那么问题来啦,为什么要这样做呢,这样做有什么好处呢?
为什么要这样做:代理模式的核心作用就是通过代理,控制对对象的访问。
我再举一个例子:比如说明星都有经纪人,有人要找某明星拍戏,那么首先处理这事的是他的经纪人,虽然拍戏需要自己拍,但是拍戏前后的一些必须要做的事等等,都由这个经纪人来处理。
这样做有什么好处:对象只需要关注自己需要执行的业务,将关注点和系统级任务分开,业务分离。
就想找明星拍戏一样,明星只需要拍戏就行,至于拍戏前的签合同,拍完戏之后的酬劳领取等,都由经纪人代理。
理解啦没有~~~
笔记最初我们有讲过代理模式分为静态代理和动态代理。上面讲了静态代理。我们再来讲讲动态代理
为什么有了静态代理还会推出动态代理?
我们观察到静态代理确实帮我们实现了基本的业务分离。但是假设xiaojiang同学除了交作业这个事情外,还有其他的事情呢?
public interface Homework { //交作业 void handHomework (); //写作业 void writeHomework (); }
@Override
//交作业的方法 public void handHomework() { beforeMethod(); xiaoJiang.handHomework(); afterMethod(); } private void afterMethod() { System.out.println("事情处理完成"); } private void beforeMethod() { System.out.println("开始处理事情"); }
假设我们需要在xiaojiang每次处理事情前都输出开始和完成,静态代理的话我们是不是得在每个方法前后都得加上beforeMethod 和afterMethod()? 这样是不是很麻烦!!!
我们来看下动态代理是如何实现的~~~~~
4、动态代理样例
在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。
现在我们编写一个类实现InvocationHandler接口,这个接口代理homework接口
public class MyInvocationHandler<T> implements InvocationHandler {
//代理对象 private T target; public MyInvocationHandler(T target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeMethod(); Object invoke = method.invoke(target, args); afterMethod(); return invoke; } private void afterMethod() { System.out.println("事情处理完成"); } private void beforeMethod() { System.out.println("开始处理事情"); } }
此时我们把beforeMethod()和afterMethod()移入到MyInvocationHandler中。
笔记到现在我们总共编写了四个类,xiaojiang + xiaozhou +homework+MyInvocationHandler。
xiaozhou 作为xiaojiang的静态代理类我们不再使用,现在我们用MyInvocationHandler代理xiaojiang交作业
好啦,编写测试类
public static void main(String[] args) { //创建xiaojiang对象 XiaoJiang xiaoJiang = new XiaoJiang("xiaojiang"); //创建xiaojiang的动态代理执行器 MyInvocationHandler handler = new MyInvocationHandler<Homework>(xiaoJiang); //创建xiaojiang的动态代理对象 Homework homework = (Homework) Proxy.newProxyInstance(Homework.class.getClassLoader(), new Class<?>[]{Homework.class}, handler); //代理xiaojiang交作业 homework.handHomework();
//代理xiaojiang写作业 homework.writeHomework(); }
这里我们执行查看结果

会发现控制台执行交作业和写作业之前都会打印事情开始和结束,完美避免了我们重复调用的麻烦!!
5、总结
动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。是因为所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以我们只要在invoke方法中统一处理,就可以对所有被代理的方法进行相同的操作了。例如,这里的方法计时,所有的被代理对象执行的方法都会被计时,然而我只做了很少的代码量,动态代理的过程,代理对象和被代理对象的关系不像静态代理那样一目了然,清晰明了。

浙公网安备 33010602011771号