博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
代理模式的理解和示例
阅读量:4551 次
发布时间:2019-06-08

本文共 4305 字,大约阅读时间需要 14 分钟。

一、是什么

1. 定义:为另一个对象提供一个替身或占位符以控制对这个对象的访问 (控制访问

2. 分类:

  远程代理: 有点类似dubbo,调用代理的方法,会被代理利用网络转发到远程执行,并把结果通过网络返回给代理,最后返回给客户

  虚拟代理: 作为创建开销大对象的代表,一般等该对象创建成功后,在委托给改对象

  安全代理: 控制访问权限

  智能代理: 提供对目标对象的额外服务

3. 实现代理的方式

  动态代理:利用反射在运行时创建代理类,并将方法的调用转发到你所指定的类

  静态代理:代理类是运行之前就被创建出来了,相对于动态代理

4. 动态代理实现方式分类

  JDK动态代理

  CGLIB动态代理

5. 使用场景:

  AOP、防火墙、缓存、同步、  

  。。。

4,类图

  • Subject抽象主体角色: 可以是抽象类或者是接口
  • RealSubject 具体的主体: 业务的真正执行者
  • Proxy 代理类: 作为主题的代理类,通过访问代理类,来访问真正的主题类

二、示例

静态代理

代理背景: 假设我要去屈臣氏买点洗漱用品,我一哥们要出去买东西,所以就让他帮我买了

 1. Subject

/** * 买洗漱用品接口 */public interface BuyCosmetics {    void shop();}

2. 在屈臣氏可以买

/** * 屈臣氏 */public class Watsons implements BuyCosmetics{    @Override    public void shop() {        System.out.println("在屈臣氏买化妆品");    }}

3. 让兄弟帮我买

/** * 我朋友帮忙跑一趟 */public class MyFriend implements BuyCosmetics {    private Watsons watsons;    public MyFriend(Watsons watsons) {        this.watsons = watsons;    }    @Override    public void shop() {        watsons.shop();    }}

4. 测试

/** * 测试类 */public class Main {    public static void main(String[] args) {        Watsons watsons = new Watsons();        MyFriend myFriend = new MyFriend(watsons);        myFriend.shop();    }}

这里实现了朋友帮我买东西的例子,和很多博客都不一样,所以如果有问题,清大家指出

JDK动态代理

理解

  1. 使用java API实现动态代理,需要注意InvocationHandler接口, 它的作用是响应代理的任何调用

   需要三步:

    1. 创建代理调用处理器

    2. 实例化代理

    3. 通过代理调用行为

代码

 1. Subject

  同上

2. 在屈臣氏可以买

  同上

3. 创建代理调用处理器

/** * 动态代理 * 作用: *  1. 生成代理对象 *  2. 指定需要代理的真实对象  * 3. 调用真实对象的操作 */public class DynamicProxy implements InvocationHandler {    /**     * 要代理的真实对象     */    private BuyCosmetics proxyObject;    /**     * 这个方法用来创建代理类,并实例化代理类     */    public BuyCosmetics getProxy(BuyCosmetics proxyObject) {        this.proxyObject = proxyObject;        return (BuyCosmetics) Proxy.newProxyInstance(proxyObject.getClass().getClassLoader(),                proxyObject.getClass().getInterfaces(), this);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        // 利用反射调用真实对象的方法, 可以在调用前后添加你的业务        Object result = method.invoke(proxyObject, args);        return result;    }}

4. 测试

public class Main {    public static void main(String[] args) {        // 1. 创建调用处理器对象        DynamicProxy dynamicProxy = new DynamicProxy();        // 2. 创建真实对象        Watsons watsons = new Watsons();        // 3. 创建动态代理类 传入目标对象        BuyCosmetics buyCosmetics = dynamicProxy.getProxy(watsons);        // 4. 执行行为        buyCosmetics.shop();    }}

CGLIB动态代理

1. Subject

  同上

2. 在屈臣氏可以买

  同上

3. 创建代理调用处理器

import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * 代理调用处理器 */public class DynamicProxy implements MethodInterceptor {    private Enhancer enhancer;    public Object getProxy(Class clazz) {        enhancer = new Enhancer();        // 设置需要代理的类        enhancer.setSuperclass(clazz);        //设置需要代理的类        enhancer.setCallback(this);        // 用于创建无参的目标对象代理类,对于有参构造器则调用Enhancer.create(Class[] argumentTypes, Object[] arguments),第一个参数表示参数类型,第二个参数表示参数的值        return enhancer.create();    }    /**     *     * @param o Subject类, 即被代理的类     * @param method Method表示拦截的方法     * @param objects 被代理类的参数     * @param methodProxy MethodProxy表示对方法的代理,invokeSuper方法表示对被代理对象方法的调用     */    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("调用前");        Object result = methodProxy.invokeSuper(o, objects);        System.out.println("调用后");        return result;    }}

4. 测试

/** * cglib动态代理 test */public class MainClient {    public static void main(String[] args) {        DynamicProxy dynamicProxy = new DynamicProxy();        BuyCosmetics watsons = (Watsons)dynamicProxy.getProxy(Watsons.class);        watsons.shop();        System.out.println(watsons.getClass().getName());    }}

5. 结果

调用前在屈臣氏买化妆品调用后com.example.demo.代理模式.CGLIB动态代理.Watsons$$EnhancerByCGLIB$$2f4d9538

三、总结

 1. 代理模式使用最多的就是,智能代理, 会为被代理对象提供额外的服务

 2. 类图和装饰器模式很像,主要看使用的目的,还有装饰器一般持有的是基类,而代理一般持有的具体的类

3. 优点:

  1)良好的扩展性。修改被代理角色并不影响调用者使用代理,对于调用者,被代理角色是透明的。

  2)隔离,降低耦合度。代理角色协调调用者和被代理角色,被代理角色只需实现本身关心的业务,非自己本职的业务通过代理处理和隔离。

4. 缺点:

  1. 访问时间可能延长

  2. 类数量增加

转载于:https://www.cnblogs.com/milicool/p/11278673.html

你可能感兴趣的文章
Ajax的封装
查看>>
Java传入参数个数不确定可用(Type ... values)
查看>>
POJ 2081
查看>>
记录下zend studio 的xdebug 在调试安装
查看>>
ES6阅读笔记
查看>>
数字基带信号分类
查看>>
移动HTML5前端性能优化指南(转)
查看>>
Jq 遍历each()方法
查看>>
Android源码分析:Telephony部分–phone进程
查看>>
关于 redis.properties配置文件及rule
查看>>
WebService
查看>>
关于Java中重载的若干问题
查看>>
Java中start和run方法的区别
查看>>
23种设计模式中的命令模式
查看>>
[转载]年薪10w和年薪100w的人,差在哪里?
查看>>
shell 日期参数
查看>>
尼姆游戏(吃花生米问题)
查看>>
最小瓶颈路
查看>>
PHP isset()与empty()的使用区别详解
查看>>
Android自定义控件(五)自定义Dialog QuickOptionDialog
查看>>