简述

代理,是一种设计模式,主要作用是为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

主要分为两大代理:静态代理、动态代理(JDK动态代理、CGLIB动态代理)

以下面的例子为例,卖房人、代理方、买房人,买卖人双方不需要打交道,通过和代理方打交道,卖房人提供房子给代理方,不需要自己去找买方,代理方有一堆卖房信息,买方直接找代理方即可


代码实现

接口

public interface IHome {void say();
}

被代理类

public class ForlanHome implements IHome{@Overridepublic void say() {System.out.println("卖程序员Forlan房子啦!!!");}
}

1、静态代理

public class HomeProxy implements IHome {IHome home;public HomeProxy(IHome home) {this.home = home;}@Overridepublic void say() {System.out.println("This is HomeProxy");home.say();}
}
 public static void main(String[] args) {ForlanHome forlanHome = new ForlanHome();HomeProxy homeProxy = new HomeProxy(forlanHome);homeProxy.say();}

2、动态代理

2.1、JDK动态代理

2.1.1、普通版

实现InvocationHandler接口重写invoke方法

public class HomeInvocationHandler implements InvocationHandler {IHome home;public HomeInvocationHandler(IHome home) {this.home = home;}/*** 重写invoke方法** @param proxy  生成的代理对象* @param method 调用的方法* @param args 方法入参* @return*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("method " + method.getName() + " start!");Object o = method.invoke(home, args);System.out.println("method " + method.getName() + " end!");return o;}
}

测试方法

public static void main(String[] args) {IHome forlanHome = new ForlanHome();IHome home = (IHome) Proxy.newProxyInstance(IHome.class.getClassLoader(),new Class[]{IHome.class},new HomeInvocationHandler(forlanHome));home.say();
}

2.1.2、反射版

引入反射封装,方便调用

public class CommonInvocationHandler<T> implements InvocationHandler {T obj;public T getProxyObj(T t) {obj = t;T proxyInstance = (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);return proxyInstance;}/*** 重写invoke方法** @param proxy  生成的代理对象* @param method 调用的方法* @param args   方法入参* @return*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("method " + method.getName() + " start..");Object o = method.invoke(obj, args);System.out.println("method " + method.getName() + " end!");return o;}
}

测试方法

public static void main(String[] args) {IHome forlanHome = new ForlanHome();CommonInvocationHandler<IHome> commonInvocationHandler = new CommonInvocationHandler<>();IHome proxyObj = commonInvocationHandler.getProxyObj(forlanHome);proxyObj.say();
}

2.2、CGLIB动态代理

第三方,需要导入jar包

 <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version></dependency>

2.2.1、普通版

实现MethodInterceptor,重写intercept方法

public class HomeMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("method " + method.getName() + " start!");Object result = null;result = methodProxy.invokeSuper(o, objects);System.out.println("method " + method.getName() + " end!");return result;}
}

测试方法

public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(ForlanHome.class); // 被代理对象的classenhancer.setCallback(new HomeMethodInterceptor()); // 设置回调,方法拦截器ForlanHome forlanHome = (ForlanHome)enhancer.create(); // 生成动态代理类forlanHome.say();
}

2.2.1、泛型版

使用泛型,封装Enhancer代码,方便调用

public class CommonMethodInterceptor<T> implements MethodInterceptor {public T getProxyObj(Class<T> tClass) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(tClass); // 被代理对象的classenhancer.setCallback(this); // 设置回调,方法拦截器return (T) enhancer.create(); // 生成动态代理类}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("method " + method.getName() + " start!");Object result = null;result = methodProxy.invokeSuper(o, objects);System.out.println("method " + method.getName() + " end!");return result;}
}

测试方法

public static void main(String[] args) {CommonMethodInterceptor<ForlanHome> commonMethodInterceptor = new CommonMethodInterceptor<>();ForlanHome proxyObj = commonMethodInterceptor.getProxyObj(ForlanHome.class);proxyObj.say();
}

总结

1、静态代理

代理对象实现被代理对象的接口,通过调用代理接口的接口,实现代理功能

  • 代理对象/被代理对象共同实现接口
  • 多态的一种应用

2、动态代理

分离代理行为和被代理对象,替被代理对象干某件事

  • JDK动态代理
    面向接口的动态代理,代理一个对象去增强面向某个接口中定义的方法
    缺点:被代理对象必须实现接口

  • CGLIB动态代理
    面向类的动态代理,重写父类方法,增强使用
    缺点: final类不能被代理

3、区别

  • 静态代理
    a、自己写生成代理类
    b、代理类和委托类的关系在运行前就确定了
  • 动态代理
    a、在程序运行期间动态生成代理类
    b、代理类和委托类的关系是在程序运行时确定

Java的两大、三类代理模式相关推荐

  1. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

  2. Java 的工厂方法及代理模式

    Java 的工厂方法及代理模式 工厂方法(FactoryMethod) 概述:定义一个用于创建对象的接口,让子类决定实例化哪一个类.FactoryMethod使一个类的实例化延迟到其子类. 适用性: ...

  3. 从底层重学 Java 之两大浮点类型 GitChat链接

    chat连接 https://gitbook.cn/gitchat/activity/5f03fdd3852a4f3686fb3366 简介 从底层,从原理,我们来重学一次 Java.两大 Java ...

  4. 从底层重学 Java 之两大浮点类型 GitChat连接

    从底层,从原理,我们来重学一次 Java.两大 Java 浮点类 Double.Float 是我们比较常用的对象,他们的源码及实现是怎样的呢? 本系列秉承所有结论尽量从源码中来,没有源码的尽量标明出处 ...

  5. Java内功修炼系列:代理模式及动态代理

    目录 一 代理模式 1.1 简介 1.2 代理模式角色定义 二 静态代理 2.1 介绍和实例 2.2 静态代理的缺点 三 动态代理 3.1 基于JDK原生动态代理实现 四 小结 一 代理模式 1.1 ...

  6. Java中的设计模式:“代理模式”的理解

    代理模式定义: 为其他对象提供一种代理以控制对这个对象的访问.在面向对象中,有时候直接访问一些对象比较麻烦,所以代理模式就是在这个对象上加上一个访问该对象的访问层.类似于很多明星的事务实际都是交给经纪 ...

  7. 【强烈推荐】Java设计模式:怒肝代理模式,可真把我榨干了!

    你的一键三连是我巨大的动力! 设计模式系列 工厂模式 (程序员必知必会) 单例模式 (程序员必知必会) 一.什么是代理模式? 其实代理模式不仅仅只存在编程中,你细想人生处处不代理呢? 一家公司老板身边 ...

  8. Java设计模式(13)----------代理模式

    原文:https://www.imooc.com/article/24850 默课道可工程师学习地址:https://www.imooc.com/article/24850 介绍 代理模式中,在客户端 ...

  9. 详解 Java 中的三种代理模式

    代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用 ...

最新文章

  1. 三维基因组染色质环(loop)结构
  2. 关于嵌入式开发,到底需要会多少门语言,做好准备了吗
  3. Android 请求PHP接口, 返回json, 开头有问号, 解决方案
  4. JSP页面Table的数据绑定
  5. android permission权限与安全机制解析(上)
  6. 买了台任天堂Switch
  7. LoadRunner 12.02 安装教程及中文语言包安装
  8. LeetCode 6. Z 字形变换(找规律)
  9. Mac中安装NetBeans方法
  10. usr/sbin/inetd
  11. 使用wireshark分析tcp报文
  12. 台式计算机把硬盘换了怎么进系统,联想台式机怎么进bios设置硬盘启动
  13. 苹果开发者账号申请的一些事
  14. 【我的区块链之路】- 理解传统Kademlia和以太坊Kademlia网络
  15. openGL之API学习(七十八)SPIR-V
  16. 单反相机的传奇—佳能单反50年辉煌之路(连载十三)
  17. SSM毕设项目毕业生就业推荐平台s0m59(java+VUE+Mybatis+Maven+Mysql)
  18. 使用WebSocket实现网页聊天室
  19. CentOS7 忘记登陆密码 修改root密码
  20. Java实现的小根堆

热门文章

  1. 美国亚马逊有望联姻顺丰 直邮商品7天到中国
  2. CaptchaUtil工具类生成GIF四则运算验证码
  3. 福特sync恢复出厂设置_新福特福克斯SYNC常用命令
  4. 【fraud detection】点击量作弊——互联网广告业的附骨之蛆!
  5. 宜信珍惜初心,吸引坚持梦想的人才
  6. 扫描仪twain协议实现,可以实现简单控制
  7. 74CMS 5.0.1后台RCE复现过程
  8. # 1987年的那件神秘的往事
  9. 海外版拼多多Temu来了 教你快速吃蛋糕
  10. 庆科EWM3080 v2.1.3(默认固件)AT指令配置方法