介绍
阅读菜鸟教程-代理模式后,得到如下信息:
意图:为其他对象提供一种代理以控制这个对象的访问
主要解决:在某些访问对象时带来的问题,比如:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制
如何解决:增加中间层
关键代码:实现与被代理类组合
应用实例:
- windows里面的快捷方式
- 买火车票不一定要去火车站买,也可以去代售点
- 一张支票或银行存单是账户中资金的代理
- Spring的AOP
静态代理
角色分析:
- 抽象角色:一般使用接口或者抽象类来实现
- 真实角色:被代理的角色
- 代理角色:代理真实角色;代理真实角色后,一般会做些附属的操作
- 客户:使用代理角色来进行一些操作
代码实现
Rent.java:抽象角色
1 | public interface Rent { |
Host.java:被代理的真实角色
1 | public class Host implements Rent { |
Proxy:代理角色
1 | public class Proxy implements Rent { |
Client:客户(真实角色,也用于测试)
1 | public class Client { |
通过代码,可以清晰看到:Host的rent()动作由Proxy代理角色执行了
优、缺点
优点:
- 可以使得我们的真实角色更加纯粹,不再关注一些公共的事情
- 公共的业务可以交由代理角色来完成(即在代理类中添加其他的方法)
- 公共业务发生扩展时,变得更加集中和方便
缺点:
- 由于一个被代理类,就对应着一个代理类,那么类多了,代理类就多了,工作量变大了,开发效率会降低(因此出现了动态代理)
动态代理
区别:动态代理的代理类是动态生成的;静态代理的代理类是我们写好的
本质:利用反射机制在运行时创建代理类
动态代理主要分为两类:基于接口的动态代理(JDK动态代理)、基于类的动态代理(cglib)
基于接口的动态代理
核心:java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。(注意是java.lang.reflect包下的)
Proxy类:提供了创建对象的静态方法,这些对象充当接口实例
Proxy
provides static methods for creating objects that act like instances of interfaces but allow for customized method invocation- 例如:To create a proxy instance for some interface
Foo
: - 已经提供的静态方法:
InvocationHandler接口:
- Each proxy instance has an associated invocation handler.
- When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the
invoke
method of its invocation handler. - 唯一的方法
代码实现
步骤:
- 写好接口
- 写好被代理类
- 创建代理模式(关键步骤:分两步:)
- 第一步:生成代理类对象(Proxy已经提供了相应的静态方法)
- 第二步:事务处理程序(继承InvocationHandler接口,并重写invoke方法)
- 注意:上面两步骤可以都写在事务处理器的类中,也可以分开写(本文就全写在一个类中了,这样以后调用的时候比较方便)
ProxyInvocationHandler.java:生成代理类,创建相应的事务处理程序
1 | import java.lang.reflect.InvocationHandler; |
Client.java:客户(真实角色,也用于测试)
1 | public class Client { |
分步解释
①
1 | //①生成代理类 |
②
1 | //②重写事务处理程序的invoke方法 |
总结
动态代理,代理的是一个接口;
- 所以可以代理所有实现这一接口的类;
静态代理,代理的是一个类;
- 所以出现一个类实现了一个接口,如果想要使用代理类,就需要对应写一个代理类