五分钟理解设计模式之代理模式

本文深入介绍了代理模式,包括静态代理和动态代理的实现方式,以找对象的场景为例,展示了静态代理的父子角色交互和动态代理的婚介所业务。动态代理分为JDK和CGLib两种,分析了它们的优缺点及在Spring中的应用。代理模式在保护目标对象、增强功能和降低耦合度方面具有优势,但也可能增加系统复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

    ​    ​代理模式(Proxy Pattern)的定义也非常简单,是指为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客服端和目标对象之间起到中介作用,代理模式属于结构型设计模式。

    ​    ​代理其实就是在原本逻辑前后增加一些逻辑,而调用者无感知

 

分类

  • 静态代理

  • 动态代理

    • jdk动态代理

    • cglib动态代理

 

目的

  • 保护目标对象

  • 增强目标对象

 

静态代理

场景

    ​    ​人到了适婚年龄,父母总是迫不及待希望早点抱孙子。而现在社会的人在各 种压力之下,都选择晚婚晚育。于是着急的父母就开始到处为自己的子女相亲,比子女自己还着急。这个相亲的过程,就是一种我们人人都有份的代理

顶层接口Person

public interface Person {    void findLove();}

儿子要找对象,实现Son类

public class Son implements Person{    public void findLove(){        System.out.println("儿子要求:肤白貌美大长腿");    }}

但是儿子比较忙去不了,只能父母帮忙去相亲了,创建father类

public class Father implements Person {    private Son person;    public Father(Son person){        this.person = person;    }    public void findLove(){        System.out.println("父亲物色对象");        this.person.findLove();        System.out.println("双方父母同意,确立关系");    }}

测试类

 Father father = new Father(new Son()); father.findLove();

 

动态代理

先看jdk代理的实现方式

我们还以找对象为例,但是这个时候需要将找对象扩展为一个产业,进而出现媒婆等更加复杂的业务场景

创建婚介所类

public class JDKMeipo implements InvocationHandler {    private Object target;    public Object getInstance(Object target) throws Exception{        this.target = target;        Class<?> clazz = target.getClass();        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);    }    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        before();        Object obj = method.invoke(this.target,args);        after();       return obj;    }    private void before(){        System.out.println("我是媒婆,我要给你找对象,现在已经确认你的需求");        System.out.println("开始物色");    }    private void after(){        System.out.println("OK的话,准备办事");    }}

假如是女孩找对象,创建类

public class Girl implements Person {    public void findLove() {        System.out.println("高富帅");        System.out.println("身高180cm");        System.out.println("有6块腹肌");    }}

测试类

Object obj = new JDKMeipo().getInstance(new Girl());obj.findLove();

CGLib

看下cglib找对象的实现

创建媒婆类

public class CGlibMeipo implements MethodInterceptor {    public Object getInstance(Class<?> clazz) throws Exception{        //相当于Proxy,代理的工具类        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(clazz);        enhancer.setCallback(this);        return enhancer.create();    }    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        before();        Object obj = methodProxy.invokeSuper(o,objects);        after();        return obj;    }    private void before(){        System.out.println("我是媒婆,我要给你找对象,现在已经确认你的需求");        System.out.println("开始物色");    }    private void after(){        System.out.println("OK的话,准备办事");    }}

 

创建顾客类

public class Customer {    public void findLove(){        System.out.println("儿子要求:肤白貌美大长腿");    }}

 

测试类

 Customer obj = (Customer) new CGlibMeipo().getInstance(Customer.class);            System.out.println(obj);            obj.findLove();

    ​    ​CGLib 代理的目标对象不需要实现任何接口,它是通过动态继承目标对象实现的动态代理

 

CGLib 和 JDK 动态代理对比

  • JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。 

  • JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。 

  • JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高。

CGLib 执行效率更高原因​:

    ​    ​CGLib 动态代理执行代理方法效率之所以比 JDK 的高是因为 Cglib 采用了 FastClass 机 制,它的原理简单来说就是:为代理类和被代理类各生成一个 Class,这个 Class 会为代 理类或被代理类的方法分配一个 index(int 类型)。这个 index 当做一个入参,FastClass就可以直接定位要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比 JDK 动态代理通过反射调用高。


Spring中的代理选择原则

1、当 Bean 有实现接口时,Spring 就会用 JDK 的动态代理 

2、当 Bean 没有实现接口时,Spring 选择 CGLib。

3、Spring 可以通过配置强制使用 CGLib,只需在 Spring 的配置文件中加入如下代码:

<aop:aspectj-autoproxy proxy-target-class="true"/>

 

总结​:

静态代理和动态的本质区别

1、静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步新增,违背开闭原则。 

2、动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则。 

3、若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成,无需修改代理类的代码。


代理模式优点

1、代理模式能将代理对象与真实被调用的目标对象分离。 

2、一定程度上降低了系统的耦合度,扩展性好。 

3、可以起到保护目标对象的作用。 

4、可以对目标对象的功能增强。

 

代理模式缺点

1、代理模式会造成系统设计中类的数量增加。 

2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。 

3、增加了系统的复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值