当前位置:首页 > CN2资讯 > 正文内容

细说代理模式代理模式

19小时前CN2资讯

代理模式,大家应该都不陌生,很多框架底层都用了代理模式,像spring、mybatis等。虽然大家都听说过代理模式,但是可能也并不是那么地了解,本文将说一下常用的代理模式。

一、代理模式介绍

代理模式其实就是找替身,要去办一件事儿,自己不去,找人代替你去,这就是代理模式。在程序中就是,为对象提供一个替身,控制替身去访问目标对象,这样做的好处是,除了目标对象能提供的功能外,还可以让替身多做一些活,即可以扩展目标对象的功能。被代理的可以是远程对象、创建时开销很大的对象或者需要安全控制的对象。

代理模式主要分为以下三种:

  • 静态代理
  • 动态代理(又叫JDK代理、接口代理)
  • cglib代理(也属于动态代理的范畴)

二、静态代理

「1、静态代理介绍:」

使用静态代理的时候,需要定义接口或者父类,被代理的对象和代理对象需要一起实现相同的接口或者继承相同的父类。

「2、应用实例:」

  • 定义一个接口: TeacherDao
  • 定义被代理的对象: TeacherDaoImpl,需要实现 TeacherDao
  • 定义代理对象: TeacherDaoProxy,也需要实现 TeacherDao
  • 要调用 TeacherDaoImpl方法时,需要先创建 TeacherDaoProxy对象,然后创建 TeacherDaoImpl对象,将 TeacherDaoImpl对象交给 TeacherDaoProxy对象,再调相关方法

代码实现:

  • TeacherDao.java:
public interface TeacherDao { void teach(); }
  • TeacherDaoImpl.java:
public class TeacherDaoImpl implements TeacherDao { @Override public void teach() { System.out.println("今天又是没妹子的一天(ノへ ̄、)"); } }
  • TeacherDaoProxy.java:
public class TeacherDaoProxy implements TeacherDao { private TeacherDao target; // 被代理的对象 public TeacherDaoProxy(TeacherDao target){ this.target = target; } @Override public void teach() { System.out.println("代理开始"); // 这里可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的前置通知 target.teach(); // 这里也可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的后置通知 System.out.println("代理结束"); } }
  • Client.java:调用代理对象
public class Client { public static void main(String[] args){ // 创建被代理的对象 TeacherDao target = new TeacherDaoImpl(); // 创建代理对象 TeacherDaoProxy proxy = new TeacherDaoProxy(target); // 通过代理对象调用方法 proxy.teach(); } }

「3、静态代理的优缺点:」

  • 优点:可以在不修改被代理对象的前提下扩展被代理的对象,做一些增强
  • 缺点:需要实现相同的接口或者继承相同的父类,所以代理类会很多,而且如果接口或者父类有改动,代理对象和被代理对象都需要维护

三、动态代理(JDK代理)

「1、动态代理介绍:」

代理对象不要实现接口,但是被代理对象还是需要实现接口的。动态代理对象的生成,利用的是JDK的API,反射包下的Proxy类,动态地在内存中构建代理对象。

「2、java.lang.reflect.Proxy:」

这个类有一个newProxyInstance方法,该方法接收三个参数,如下:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

「3、应用实例:」

  • 定义一个接口:TeacherDao
  • 定义被代理的对象:TeacherDaoImpl,需要实现TeacherDao
  • 定义一个代理工厂ProxyFactory,有一个getProxyInstance方法,需要传入被代理的对象,然后返回代理对象实例,通过代理对象调用被代理对象的方法

代码实现:

  • TeacherDao.java:
public interface TeacherDao { void teach(); }
  • TeacherDaoImpl.java:
public class TeacherDaoImpl implements TeacherDao { @Override public void teach() { System.out.println("今天又是没妹子的一天(ノへ ̄、)"); } }
  • ProxyFactory.java
public class ProxyFactory { private Object target; // 被代理的对象 public ProxyFactory(Object target){ this.target = target; } // 给被代理的对象生成一个代理对象 public Object getProxyInstance(){ // 参数1:指定被代理对象的类加载器 // 参数2:被代理对象实现的接口类型 // 参数3:事件处理,执行被代理对象的方法 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK代理开始"); // 调用方法,args的方法的参数 Object returnValue = method.invoke(target, args); System.out.println("JDK代理结束"); // 将执行结果return return returnValue; } }); } }
  • Client.java:通过代理调用方法
public class Client { public static void main(String[] args){ // 创建被代理的对象 TeacherDao target = new TeacherDaoImpl(); // 创建代理对象 TeacherDao proxy = (TeacherDao) new ProxyFactory(target).getProxyInstance(); // 通过代理对象调用被代理对象的方法 proxy.teach(); } }

四、cglib代理

「1、cglib代理介绍:」

静态代理和动态代理,被代理的对象,都需要实现接口,如果一个类没实现任何接口的,那就要用cglib代理了。cglib代理也叫子类代理,它会在内存中构建一个子类对象,从而实现对被代理对象的扩展。cglib代理底层是通过一个叫ASM的字节码处理框架来转换字节码并生成新的类从而实现代理的。被代理的类不能为final,否则会报错。被代理对象的方法如果是final/static,就不会被拦截,即不会执行被代理对象额外的业务方法。

「2、应用实例:」

  • 首先要添加cglib相关依赖:
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
  • TeacherDaoImpl.java:
public class TeacherDaoImpl implements TeacherDao { @Override public void teach() { System.out.println("今天又是没妹子的一天(ノへ ̄、)"); } }
  • CglibProxyFactory.java:
// 需要实现MethodInterceptor并重写其方法 public class CglibProxyFactory implements MethodInterceptor { private Object target; public CglibProxyFactory(Object target){ this.target = target; } /** * 返回target的代理对象 * @return */ public Object getProxyInstance(){ // 1. 创建工具类 Enhancer enhancer = new Enhancer(); // 2. 设置父类 enhancer.setSuperclass(target.getClass()); // 3. 设置回调函数 enhancer.setCallback(this); // 4. 创建子类对象,即代理对象 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("CGLIB代理开始"); Object returnValue = method.invoke(target, args); System.out.println("CGLIB代理结束"); return returnValue; } }
  • Client.java:通过代理调用方法
public class Client { public static void main(String[] args){ // 创建被代理的对象 TeacherDaoImpl target = new TeacherDaoImpl(); // 获取代理对象,并将被代理对象传给代理对象 TeacherDaoImpl proxy = (TeacherDaoImpl) new CglibProxyFactory(target).getProxyInstance(); // 执行方法,触发intecept方法,从而实现执行被代理对象的方法 proxy.teach(); } }
    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/24530.html

    分享给朋友:

    “细说代理模式代理模式” 的相关文章

    测试IP地址的重要性与常用工具推荐

    在网络管理中,测试IP地址的重要性不可忽视。每当我遇到网络问题,测试IP地址就成了第一步。了解IP地址的状态和性能,不仅能帮助我找到问题所在,还能快速解决网络故障。这就像是医生给病人做检查,只有找出病因,才能对症下药。 我们在进行网络操作时,IP地址就像每台设备的身份名片。借助一些功能强大的工具,我...

    使用newcom598优惠码注册域名,享受超值价格

    什么是newcom598优惠码? 我想和大家分享一个超值的优惠信息,那就是newcom598优惠码。这是一个专为Namecheap的新用户设计的优惠码,意在帮助刚开始建立自己在线业务的人以超优惠的价格注册.COM域名。通过这个优惠码,新用户可以以仅$5.98的价格获得首年的.COM域名,这样算下来在...

    RackNerd与ColoCrossing的对比分析:选择适合你的数据中心服务

    RackNerd vs ColoCrossing概述 在当前的互联网服务市场中,RackNerd与ColoCrossing都是备受关注的数据中心服务提供商。它们各自的成长背景和市场定位都显示出一些显著的差异。RackNerd成立于2019年,专注于提供低价 VPS 和服务器租用服务,屡次推出吸引人的...

    全球云服务厂商排名分析:选择适合你的云服务平台

    在如今这个数字化快速发展的时代,云服务已经成为企业运营的核心。全球云服务市场正在以前所未有的速度增长,吸引了众多企业选择不同的云服务提供商。作为用户,当我们谈论云服务厂商时,不可避免地会提到几个行业巨头,显然,他们的市场份额和影响力在整个行业中是不可忽视的。 近年以来,亚马逊网络服务(AWS)稳居全...

    VPS优惠活动解析:如何选择最划算的虚拟专用服务器方案

    在当今互联网环境中,VPS(虚拟专用服务器)为企业和个人用户提供了灵活、高效的解决方案。随着云计算的普及,VPS逐渐成为许多用户的首选。不管是建站、开发、还是日常的数据处理,选择一款合适的VPS至关重要。而在不同的VPS服务提供商中,优惠活动往往能让用户以更实惠的价格体验高质量的服务。 什么是VPS...

    甲骨文云免费IPv6服务详解:轻松配置与应用技巧

    甲骨文云,作为一个综合性的云服务提供商,正迅速崛起于众多的云技术平台之中。它不仅拥有强大的数据处理能力,还提供了多种免费的云服务选项,让个人和企业都能以更低的成本探索并使用云计算的强大功能。首先,我对甲骨文云的快速适应能力和多种灵活服务感到印象深刻,尤其是它的免费套餐项目,吸引了不少用户前来试用。...