代理模式Proxy
问题提出:benchMark 性能测试,不修改原来代码,记录代码的运行时间:
- 继承实现:类爆炸
- 手动组合:自己使用代理类包装,代理类里面调用被代理对象,附加上自己的事情。
- 实现同一个接口可以实现代理的嵌套,当需要实现多个代理功能的时候
- 限制就****是要实现同一个接口
- 实现同一个接口可以实现代理的嵌套,当需要实现多个代理功能的时候
- 全能代理:不同接口,解耦,动态代理,运行时候生成。
- **java.lang.reflect.Proxy **:通过反射getClass(Loader),不需要读取源码,只需要二进制字节码就得到属性和方法。
- 被代理类需要有接口:代理遵循接口才能伪装为服务的对象,让外界调用接口即可,我们负责替换
- cglib:底层也是asm。但是其实是生成了一个被代理类的子类,所以当一个类是final的时候,是不可以使用这个来实现代理的
- asm:甚至可以代理final,因为直接修改二进制字节码,所以随意
- 注意字节码class文件是二进制的,使用IDE打开的时候是显示反编译之后的代码,其实不是文件真正存放的内容
- **java.lang.reflect.Proxy **:通过反射getClass(Loader),不需要读取源码,只需要二进制字节码就得到属性和方法。
静态代理--自己包装
被包装和包装类都要实现一样的接口,
构造的时候都使用接口作为形参,传递实参的时候使用接口的具体实现类
代理类中调用的时候都使用面向接口调用,运行时候根据函数的参数替换为具体的实现类
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) 收藏 举报
浙公网安备 33010602011771号