目录
一、代理模式
二、静态代理
三、动态代理(为了解决静态代理的缺点)
1.什么是代理模式?
代理模式就是给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
通俗的来讲代理模式就是我们生活中常见的中介。
举例说明,假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下
特征:代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
代理模式(Proxy)结构图
Subject类,定义了RealSubject和Proxy的共用接口,这样就可在任何使用RealSubject的地方可以使用Proxy。(可称为抽象角色)
RealSubject类,定义了Proxy所代表的真是实体(也就是上述所说的委托类,称为真是角色)
Proxy类,保存了一个引用使得代理可以访问实体,并提供了一个与Subjet的接口相同的接口,这样代理就可以用来替代实体。(中介,称为代理角色)
2.为什么要用代理模式?
1)开闭原则,增加功能(代理模式在不修改原有代码的基础上,通过代理类扩展委托类的功能。)
比如:我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
2)中介隔离作用
(在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。)
3.有哪几种代理模式?
1)静态代理
由程序员创建或特定工具自动生成源代码,在对其编译。在程序运行之前,代理类.class文件就已经被创建了
2)动态代理
能够在程序运行时JVM才为被代理对象生成代理对象。
简单代码实现:
// 接口 interface IStar { void sing(); } // 真实对象 class LDHStar implements IStar { @Override public void sing() { System.out.println("刘德华唱歌"); } } // 代理类需要有真实对象的控制权 (引用) class ProxyManger implements IStar { // 真实对象的引用 private IStar star; public ProxyManger() { super(); } public ProxyManger(IStar star) { super(); this.star = star; } @Override public void sing() { System.out.println("唱歌前准备"); star.sing(); System.out.println("善后工作"); } } class Test{ public static void main(String[] args) { // 创建明星对象 IStar ldh = new LDHStar(); ProxyManger proxy = new ProxyManger(ldh); proxy.sing(); } }
结果:
静态代理总结:
优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展.
缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增 加方法,目标对象与代理对象都要维护.
1.动态代理和静态代理角色一样
2.动态代理的代理类是动态生成的,不是我们直接写好的
3.动态代理分为两大类:基于接口的动态代理,基于类的动态代理
基于接口----JDK动态代理
基于类----cglib
java字节码实现---javasist
需要了解的两个类:
invocationHandle类:调用处理程序,返回结果
proxy类:提供创建动态代理类和实例的静态方法
//目标类接口interface IDog{ void run(); } //目标类 class GunDog implements IDog{ @Override public void run() { System.out.println("猎狗在跑"); } } class DogUtils{ public static void method1() { System.out.println("增强方式一"); } public static void method2() { System.out.println("增强方式二"); } } class MyInvocationHandle implements InvocationHandler{ private Object target; public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { DogUtils.method1(); method.invoke(target, args); DogUtils.method2(); return null; } } //生产代理对象的工厂 class MyProxyFactory{ public static Object getProxy(Object target) { MyInvocationHandle handle = new MyInvocationHandle(); handle.setTarget(target); Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handle); return proxy; } } public class ProxyDemo { public static void main(String[] args) { IDog dog = new GunDog(); IDog proxy =(IDog) MyProxyFactory.getProxy(dog); proxy.run(); } }
结果:
总结:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能使用动态代理,因此这也算是这种方式的缺陷。