Java代理
代理
引入
总结梳理下代理相关的知识点,按照设计模式之代理模式、静态代理、动态代理的思路展开
代理模式
设计模式中的一种,某些情况下客户不想直接访问对象,进而借助中介帮忙完成某项任务,这个中介对象就是代理。
定义:某些原因需要给对象提供代理以控制对象的访问。访问对象不能直接引用目标,代理对象作为访问对象和目标对象间的中介。
优点:在访问对象和目标对象间起到中介和保护目标的作用;扩展目标对象功能;访问对象和目标对象分离,降低耦合度
缺点:导致类的数量增加;访问对象和目标对象间增加对象,请求速度变慢;增加系统复杂度
客户要访问真实主题,通过代理的方式访问,代理内部会调用主题的请求方法,但同时在其前后执行增强方法,可以通过此方式控制或拓展真实主题的功能。
代理模式:根据代理的创建时期进行划分
动态代理:程序运行期间,工具类动态生成代理类的class字节码文件缓存在内存,运用反射机制实例化代理对象
静态代理:自己手写代理
应用场景
无法或不想直接引用某个对象或访问某个对象困难,用代理对象访问。代理模式的主要目的:保护目标对象;增强目标对象
- 远程代理:隐藏访问目标存在于不同地址的事实,方便客户端访问。例如网盘在我的电脑生成的虚拟影盘图标,实际访问的是网盘
- 虚拟代理:要创建的目标对象开销大。如下载大文件,短时间无法完成,先用小比例虚拟对象替换,提升用户体验
- 安全代理:控制不同类客户对真实对象的访问权限
- 智能指引:调用目标对象时,代理部分额外处理功能,如计算真实对象的引用次数
- 延迟加载:延迟目标的加载,提高系统性能。如hibernate存在属性和关联表的延迟加载
静态代理
手动代理类,实现目标类的接口,引入目标类的实例,重写接口方法内,调用目标类实例方法并进行增强。
可以在不改变类的情况下,实现对类的增强。但所谓静态就是在创建代理类时,接口和被代理类y已确定下来,代理类就是只能代理一种类。实际开发过程中,有多个类和接口需要代理增强的时候,这样会产生大量的冗余和复杂性,故推荐使用动态代理
动态代理
程序运行时创建的代理方式称为动态代理。静态代理是程序运行前,已经编译完成。动态代理是在运行时根据Java代码中的‘指示’动态生成的。动态代理相较于静态代理优势是方便对所有代理类统一管理,若是使用静态代理则每个都需要生成代理,很麻烦。代理方式有两种:JDK动态代理(接口)和CGLIB动态代理(继承)
JDK动态代理:Java自动生成代理类class对象,保存在内存中,通过反射获取代理类的构造方法,进而创建代理类的实例对象
public class RenterInvocationHandler<T> implements InvocationHandler{
//被代理类的对象
private T target;
public RenterInvocationHandler(T target){
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//代理过程中插入其他操作
System.out.println("租客和中介交流");
Object result = method.invoke(target, args);
return result;
}
}
CGLIB动态代理:也叫子类代理,通过在内存中构建一个子类,在子类用方法拦截的方式拦截所有父类方法的调用,然后加入自己的操作。因为使用的是继承,不能代理final类
public class ProxyFactory<T> implements MethodInterceptor {
private T target;
public ProxyFactory(T target) {
this.target = target;
}
// 创建代理对象
public Object getProxyInstance() {
// 1.cglib工具类
Enhancer en = new Enhancer();
// 2.设置父类
en.setSuperclass(this.target.getClass());
// 3.设置回调函数
en.setCallback(this);
return en.create();
}
//拦截方法
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("开始事务...");
// 执行目标对象的方法
Object result = method.invoke(target, args);
System.out.println("提交事务...");
return result;
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤