代理模式Proxy

问题提出:benchMark 性能测试,不修改原来代码,记录代码的运行时间:

  • 继承实现:类爆炸
  • 手动组合:自己使用代理类包装,代理类里面调用被代理对象,附加上自己的事情。
    • 实现同一个接口可以实现代理的嵌套,当需要实现多个代理功能的时候
      • 限制就****是要实现同一个接口
  • 全能代理:不同接口,解耦,动态代理,运行时候生成。
    • **java.lang.reflect.Proxy **:通过反射getClass(Loader),不需要读取源码,只需要二进制字节码就得到属性和方法。
      • 被代理类需要有接口:代理遵循接口才能伪装为服务的对象,让外界调用接口即可,我们负责替换
    • cglib:底层也是asm。但是其实是生成了一个被代理类的子类,所以当一个类是final的时候,是不可以使用这个来实现代理的
    • asm:甚至可以代理final,因为直接修改二进制字节码,所以随意
      • 注意字节码class文件是二进制的,使用IDE打开的时候是显示反编译之后的代码,其实不是文件真正存放的内容

静态代理--自己包装

被包装和包装类都要实现一样的接口,

构造的时候都使用接口作为形参,传递实参的时候使用接口的具体实现类

代理类中调用的时候都使用面向接口调用,运行时候根据函数的参数替换为具体的实现类

interface Movable {
    void move();
}
package com.deltaqin.designPattern.d08_proxy;

// 要求代理类和被代理实现一样的接口
// 构造的时候都使用接口作为形参,传递实参的时候使用接口的具体实现类
// 代理类中调用的时候都使用面向接口调用,运行时候根据函数的参数替换为具体的实现类
public class Tank implements Movable {

    @Override
    public void move() {
        System.out.println("Tank moving");
    }

    public static void main(String[] args) {

        Tank t = new Tank();
        TankTimeProxy ttp = new TankTimeProxy(t);
        TankLogProxy tlp = new TankLogProxy(ttp);
        tlp.move();
    }
}

class TankTimeProxy implements Movable {
    Movable m;

    public TankTimeProxy(Movable m) {
        this.m = m;
    }

    @Override
    public void move() {
        long start = System.currentTimeMillis();
        m.move();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

class TankLogProxy implements Movable {
    Movable m;

    public TankLogProxy(Movable m) {
        this.m = m;
    }

    @Override
    public void move() {
        System.out.println("start moving...");
        m.move();
        long end = System.currentTimeMillis();
        System.out.println("stopped!");
    }
}
  • Subject:程序中的业务接口,定义了相关的业务方法。
  • RealSubject:实现了 Subject 接口的业务实现类,其实现中完成了真正的业务逻辑。
  • Proxy:代理类,实现了 Subject 接口,其中会持有一个 Subject 类型的字段,指向一个 RealSubject 对象。

在使用的时候,会将 RealSubject 对象封装到 Proxy 对象中,然后访问 Proxy 的相关方法,而不是直接访问 RealSubject 对象。在 Proxy 的方法实现中,不仅会调用 RealSubject 对象的相应方法完成业务逻辑,还会在 RealSubject 方法执行前后进行预处理和后置处理。

  • 预处理逻辑,后置处理逻辑。
  • 实现延迟加载。延迟加载可以有效地避免数据库资源的浪费,用户在访问数据库时,会立刻拿到一个代理对象,此时并没有执行任何 SQL 到数据库中查询数据,代理对象中自然也不会包含任何真正的有效数据;当用户真正需要使用数据时,会访问代理对象,此时会由代理对象去执行 SQL,完成数据库的查询。MyBatis 也提供了延迟加载功能,原理大同小异,具体的实现方式也是通过代理实现的。

会导致:代理类爆炸

Proxy

cglib

Cglib 其实就是生成了被代理类的子类

注意final修饰的不可以

posted on 2025-10-14 23:01  chuchengzhi  阅读(6)  评论(0)    收藏  举报

导航

杭州技术博主,专注分享云计算领域实战经验、技术教程与行业洞察, 打造聚焦云计算技术的垂直博客,助力开发者快速掌握云服务核心能力。

褚成志 云计算 技术博客