设计模式——代理模式12

代理模式给某对象提供一个代理对象,由代理对象来控制对原对象的引用。该模式经常出现在系统框架或相关组件中,如Spring框架如何解决循环依赖,在Mybatis 定义 Dao 层相关接口 不写实现 如何通过注解或者xml映射到对应到sql语句。下面介绍 静态代理和动态代理(JDK ,cglib代理)
设计模式,一定要敲代码理解

静态代理

在这里插入图片描述

被代理实体抽象

public interface Isend {
    void toSend();
}

被代理实体实现

public class Send implements Isend {
    @Override
    public void toSend() {
        System.out.println("送快递中");
    }
}

静态代理类

/**
 * @author ggbond
 * @date 2024年04月09日 15:24
 * 静态代理 类
 */
public class staticProxy implements Isend{
    private Isend send;

    public staticProxy(Isend send) {
        this.send = send;
    }
    //方法增强
    @Override
    public void toSend() {
        before();
        send.toSend();
        after();
    }
    public  void  before(){
        System.out.println("代理人员即将进行配送");
    }

    public  void  after(){
        System.out.println("代理人完成配送");
    }
}

测试与结果

public class Main {
    public static void main(String[] args) {
        Isend s1=new Send();
        s1.toSend();
        System.out.println("----------");
        Isend proxy=new staticProxy(s1);
        proxy.toSend();
    }
}
送快递中
----------
代理人员即将进行配送
送快递中
代理人完成配送

动态代理

在这里插入图片描述

JDK 代理

核心 实现 InvocationHandler 接口 ,通过反射实现代理

/**
 * @author ggbond
 * @date 2024年04月09日 15:35
 * JDK代理
 */
public class myIvocationhandler  implements InvocationHandler {
    private   Object target;

    public myIvocationhandler(Object target) {
        this.target = target;
    }
    public  void  before(){
        System.out.println("JDK代理人员即将进行配送");
    }

    public  void  after(){
        System.out.println("JDK代理人完成配送");
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object;
        if ("toSend".equals(method.getName())){ //反射拦截注入
            before();
            object = method.invoke(target, args);
            after();
        }else {
            object = method.invoke(target, args);
        }
        return  object;
    }
}

cjlib 代理

cglib 代理 ,需导入 cglib.jar, ASM.jar包
核心 实现MethodInterceptor 接口,与上述写法类似。

public class myInterceptor  implements MethodInterceptor {
    private   Object target;

    public myInterceptor(Object target) {
        this.target = target;
    }
    public  void  before(){
        System.out.println("cglib代理人员即将进行配送");
    }

    public  void  after(){
        System.out.println("cglib代理人完成配送");
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object object;
        if ("toSend".equals(method.getName())){ //反射拦截注入
            before();
            object = method.invoke(target, objects);
            after();
        }else {
            object = method.invoke(target, objects);
        }
        return  object;
    }
}

测试与结果

/**
 * @author ggbond
 * @date 2024年04月09日 16:00
 */
public class Main {
    public static void main(String[] args) {
        Isend s1= new Send();
        s1.toSend();
        System.out.println("-----------");

        //JDK proxy 基于接口 代理
        Isend JDKproxy=(Isend) Proxy.newProxyInstance(s1.getClass().getClassLoader(),
                                s1.getClass().getInterfaces(),
                                new myIvocationhandler(s1));
        JDKproxy.toSend();
        System.out.println("-----------");

        //cjlib proxy  继承代理
        Send s2 = new Send();
        Enhancer enhancer=new Enhancer();
        enhancer.setCallback(new myInterceptor(s2));
        enhancer.setSuperclass(s2.getClass());
        Send cglibproxy =(Send) enhancer.create();
        cglibproxy.toSend();

    }
}
送快递中
-----------
JDK代理人员即将进行配送
送快递中
JDK代理人完成配送
-----------
cglib代理人员即将进行配送
送快递中
cglib代理人完成配送

总结

静态代理 需对代理目标进行”量身定制“,当目标新加方法时,代理类也要对应加实现。不利于扩展。
动态代理 :这里介绍 基于接口实现的JDK代理与cglib代理(继承代理)

  1. 代理对象的生成方式:JDK代理是基于接口的代理,要求目标对象必须实现一个接口,代理类会实现同样的接口,并在其中调用目标对象的方法。而CGLIB代理则能够代理没有实现接口的类,通过继承目标类生成子类的方式来创建代理对象。
  2. 底层实现技术:JDK代理主要基于反射机制,通过InvocationHandler接口来定义代理类的行为。在代理对象的方法被调用时,会触发InvocationHandler接口的invoke()方法。而CGLIB代理则使用底层的字节码技术,通过Enhancer类和MethodInterceptor接口来创建代理对象,工作通过字节码增强技术完成。
  3. 性能差异:JDK代理由于基于反射机制,因此在调用代理方法时性能上可能不如CGLIB代理。而CGLIB代理通常被认为性能更好,因为它通过直接操作字节码生成新的类,避免了使用反射的开销。
    使用场景:JDK代理适用于接口驱动的代理场景,当不涉及具体类,只关心接口定义时非常适用。而CGLIB代理则在需要代理没有实现接口的类,或者需要通过继承来提供增强功能的场景更适用。
  4. 依赖问题:JDK代理不需要添加任何额外依赖,因为它是基于JDK自带的API。而CGLIB代理则需要添加CGLIB库的依赖。

代码下载

代码下载

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值