一步一步详细解析代理模式


一、静态代理

设置一个场景,小明想买台宝马,但是他对车一无所知,所以他拜托了自己的好朋友小李帮忙,那么代码如下

他们都是人

/**
 * 人类需求
 */
public interface People {

    void need();

}

小明

/**
 * 对车一无所知的小明
 */
public class Xiaoming implements People {

    public void need() {
        System.out.println("我要买宝马车");
    }
}

小李加入了对车的新需求

/**
 * 车中高玩
 */
public class Xiaoli implements People {

    private Xiaoming xiaoming;

    public Xiaoli(Xiaoming xiaoming) {
        this.xiaoming = xiaoming;
    }

    public void need() {
        System.out.println("一键启动,无钥匙进入");
        xiaoming.need();
        System.out.println("四个电吸门");
    }
}

测试一下

 public static void main(String[] args) {
       People xiaoli = new Xiaoli(new Xiaoming());
        xiaoli.need();
 }

在这里插入图片描述

紧随着问题来了,小红觉得小李很厉害,也想让他帮忙买车并给了一笔巨款,

/**
 * 小红
 */
public class Xiaohong implements People {

    public void need() {
        System.out.println("我要买粉色车");
    }
}

但是小李觉得钱不钱的无所谓,主要是对于美女不能拒绝,但是考虑到可能小红还有闺蜜甲,乙,丙。。。等等,他渐渐的优点力不从心。他苦思冥想,觉得,为什么我不能做个车贩子呢,于是便有了

二、动态代理

1.JDK动态代理

1.1 代码

代码如下(示例):

/**
 * 车贩子小李
 */
public class Jdkchefanzi implements InvocationHandler {

    private People people;

    public People getInstance(People people){
        this.people=people;
        Class<? extends People> clazz = people.getClass();
        return (People) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始大数据搜索车辆");
        Object invoke = method.invoke(people, args);
        System.out.println("车辆匹配上");
        return invoke;
    }
}

测试一下

 public static void main(String[] args) {
 
        Jdkchefanzi Xiaohong = new Jdkchefanzi();
        Xiaohong.getInstance(new Xiaohong()).need();

        Jdkchefanzi xiaomin = new Jdkchefanzi();
        xiaomin.getInstance(new Xiaoming()).need();
        People xiaoli = new Xiaoli(new Xiaoming());
}

在这里插入图片描述

1.1 原理

那么它的原理是啥样的呢
通过debug我们可以看到,最后生成的一个对象时$proxy0,由他来执行我们的方法,然后我们把他生成一下看看
在这里插入图片描述
proxy
在这里插入图片描述
我们可以看到他继承了proxy实现了我们接口,在need()方法中调用了一个super.h.invoke(),这个h其实就是小明或者小红的那个类。这也说明了使用jdk代理必须得有接口且没有继承;但是吧,如何我继承了呢,如果我没有接口呢,我是个普通类呢,再加上我们知道,在java中使用反射是效率很低的一件事,所以我们换一种方式

2.CGLib动态代理

代码如下(示例):

/**
 * 车贩子小李
 */
public class Cglibchefanzi implements MethodInterceptor {

    static{
        //这行代码的作用是将cglib生成的代码输出到f盘file目录里边
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F://file");
    }

    public Object getInstance(Class<?> clazz){
        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 {
        System.out.println("开始大数据搜索车辆");
        Object o1 = methodProxy.invokeSuper(o, objects);
        System.out.println("车辆匹配上");
        return o1;
    }
}

测试一下
在这里插入图片描述

没问题,然后我们来看看原理,去f盘看看cglib生成的文件在这里插入图片描述

一共三个文件,分别是

  1. 代理类的fastclass
  2. 目标类
  3. 目标类的fastclass

那么fastclass技术是什么呢,简单来说就是给你的方法做不同的序号,例如说给你的toString()方法标志位1,我如果要调用的时候直接调用序号为1的方法即可,使用switch ()case 如网上这幅图
在这里插入图片描述
这就是fastclass技术。

注意看这个在这里插入图片描述
所以说jdk是基于接口实现的,cglib是基于继承实现的。本质区别


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值