当前位置: 首页 > news >正文

Java中的代理

核心结论:代理类是Java中一种特殊类,它可替代目标类执行操作,能在不修改目标类代码的前提下,对其方法进行增强或控制访问,是实现AOP(面向切面编程)的重要技术基础。



为什么需要代理类?

在实际开发中,我们常需为目标类添加日志记录、权限校验、事务管理等通用功能。若直接修改目标类,会违反开闭原则(对扩展开放、对修改关闭)。代理类则可作为中间层,在调用目标方法前后嵌入额外逻辑,实现功能增强的同时,保持目标类的独立性。

代理类有哪些类型?

Java中的代理类主要分为两类,核心区别如下:

类型                            实现方式                                                                        特点                           
静态代理              手动编写代理类,实现与目标类相同的接口            实现简单,但目标类增多时代理类会膨胀                                                           适用场景    :     目标类少且接口稳定的场景 
动态代理              运行时通过反射动态生成代理类                                 无需手动编写代理类,灵活性高 目标类多、                                                     适用场景    :        需统一增强逻辑的场景 

动态代理又可细分为JDK动态代理(基于接口)和CGLIB动态代理(基于继承,可代理无接口的类)。

一.静态代理

静态代理如何实现呢?

下面我们来看例子,‘假设我们要买一件大小为100码的衣服,这时候需要先有一个制衣服厂,但是我峨嵋你要怎末调用这个制衣方法呢,在Test里直接调用吗?

像这样?显然是不行的,因为用户怎末能直接创建一个源代码类型的对象呢?那样数据不就会用户更改了吗?所以不能调用 ,所以这时候就需要用到代理类,通过代理对象调用到核心对象的核心方法,从而实现购买

工厂(方法)----接口(告诉代理主要方法是啥,要调用哪个)-------代理(接受用户数据调用接口和方法)-------用户(需求购买)

下面来看代码

首先有一个制衣工厂

然后有一个代理对象,但是这时候问题又来了,通过这个代理对象我们怎末知道这个工厂是干啥的?换句话来说我们怎么知道里面的代码?怎末知道到底调用工厂里多个代码的哪一个?,所以这时候就要用接口来告诉代理商核心代码是啥,到底调用哪个方法 ******

 接下来是接口:

最后就是用户调用代理类,代理类在调用接口里的方法:

 

 总结:

核心结论:静态代理是Java代理模式的一种实现,指在编译期就已明确代理类的代码,且代理类与目标类实现相同接口,通过显式调用目标类方法,在其前后嵌入增强逻辑,从而实现对目标类的功能扩展。

静态代理的关键特征是什么?

- 编译期确定:代理类的源码需手动编写,与目标类一同编译为class文件,运行前代理类就已存在。

- 接口依赖:代理类和目标类必须实现同一个业务接口,确保代理类可替代目标类对外提供服务(遵循里氏替换原则)。

- 显式关联:代理类中通常会持有目标类的实例,在代理方法中直接调用目标类的对应方法。

静态代理的实现逻辑是怎样的?

1. 定义一个接口(如 UserService ),声明目标类和代理类共同的方法(如 saveUser() )。

2. 目标类(如 UserServiceImpl )实现该接口,编写核心业务逻辑。

3. 代理类(如 UserServiceProxy )同样实现接口,在其方法中:

- 调用目标类的对应方法(如 userService.saveUser() )。

- 在调用前后添加增强逻辑(如日志打印、参数校验)

二.动态代理

静态代理会有很多弊端:

- 代码冗余:每增加一个目标类,若需代理则需新增一个代理类,导致类数量激增。

- 维护成本高:当接口方法修改时,目标类和所有代理类都需同步修改,违背开闭原则。

即当工厂太多时,只能自己手写增加,太过繁琐,所以就有了动态代理

所谓动态代理就是让代理类根据工厂数目生成代理对象,,从而达到一个代理一个工厂

下面我们来看代码:

区别就是代理类动态代理类是有一个全局变量target,接受Object数据,静态代理则是直接写代理工厂的名称

 那麽具体过程有啥区别呢?

main方法入栈之后,会获取这个代理类里面的targrt,然后这个target会根据接口来调用工厂里的方法这就是动态代理

 工厂:

package com.qcby;public class ClothesFactory implements makeClothes{public void makeClothes(Integer size){System.out.println("为您定制了一款大小为"+size+"的衣服");}}

接口:

package com.qcby;public interface makeClothes {public void makeClothes(Integer size);
}

代理类:

package com.qcby;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** InvocationHandler*/
public class 动态代理类 implements InvocationHandler {//创建目标对象 ----------》没有直接指明我到底代理的谁?private Object target;public 动态代理类(Object target) {this.target = target;}/*** 获取目标对象的接口:知道目标类的核心方法是谁了。* @return*/public Object getProxy(){return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}/*** 这个方法是jdk给咱们提供的,帮助咱们去调用目标对象方法* @param proxy* @param method --------》目标对象的核心方法* @param args  ----------->目标对象核心方法参数* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {FrontService();method.invoke(target,args);endService();return null;}//前置服务public void FrontService() {System.out.println("根据您的需求进行市场调研");}//前置服务public void endService() {System.out.println("为您提供一条龙的包办服务");}}

用户:

package com.qcby;public class XiaoHong {public static void main(String[] args) {//让代理对象引用目标对象动态代理类 d = new 动态代理类(new ClothesFactory());//2.获取目标对象的接口makeClothes makeClothes = (com.qcby.makeClothes) d.getProxy();makeClothes.makeClothes(100);动态代理类 c = new 动态代理类(new ShootFactory());}
}
总结:

核心结论:动态代理是Java中在运行时动态生成代理类的技术,无需手动编写代理代码,能为目标类动态添加增强逻辑,是实现灵活解耦和批量功能增强的关键手段。

动态代理的核心特征是什么?

- 动态生成:代理类在程序运行时由JVM通过反射机制动态创建,而非编译期预先定义。
- 接口依赖(JDK动态代理):默认要求目标类实现接口,代理类会动态实现相同接口(CGLIB动态代理可突破此限制,基于继承实现)。
- 统一增强:可通过一个代理逻辑处理多个目标类,避免静态代理的类膨胀问题。


动态代理的核心价值是什么?

1. 减少代码冗余:无需为每个目标类编写代理类,统一通过拦截器实现增强逻辑。
2. 提高灵活性:运行时可动态指定目标类和增强行为,适应多变的业务需求。
3. 支撑框架底层:是Spring AOP、MyBatis插件等框架实现的核心技术,实现事务管理、日志拦截等切面功能。

总结:

动态代理通过运行时动态生成代理类,解决了静态代理的扩展性问题,既能在不修改目标类的前提下增强功能,又能适应大量目标类的统一处理场景,是Java中实现面向切面编程和框架灵活性的核心技术之一。

http://www.dtcms.com/a/304978.html

相关文章:

  • 2025年06月03日 Go生态洞察:语法层面的错误处理支持
  • word中rtf格式介绍
  • 游戏分享网站|基于SprinBoot+vue的游戏分享网站系统(源码+数据库+文档)
  • #C语言——学习攻略:深挖指针路线(三)--数组与指针的结合、冒泡排序
  • 前端路由
  • Mysql 图形化界面
  • JVM全面解析
  • 【HTML】浅谈 script 标签的 defer 和 async
  • JAVA中JDK8新特性(Stream流)
  • Unity打包后,在Windows7系统上无法播放VideoPlayer视频
  • Python 中数据的位运算和状态编码(掩码)详解
  • SeeMoE:从零开始实现一个MoE视觉语言模型
  • 项目质量如何把控?核心要点分析
  • Python入门第四课:高级特性与实战:应用列表推导式与生成器
  • Makefile 与 CMake 关系指南
  • 基于 xlsx-js-style 的 Excel 导出工具实现导出excel
  • JSON解析(day20)
  • 飞机大战小游戏
  • string
  • 如何进行项目复盘?核心要点分析
  • 从线下到线上:解析足浴按摩平台如何实现成本降低80%的技术方案
  • java基础面试题(5)
  • 高精度惯性导航IMU传感器价格供应商
  • 数据处理和统计分析——04 Pandas DataFrame
  • Python的‌魔法方法‌
  • Java学习第八十七部分——四次挥手
  • Java设计模式之《备忘录模式》
  • 80V降5V,输出电流4A,应用于车载充电器
  • 工厂方法模式 Factory Method Pattern
  • 监控场景视频质量异常修复:陌讯动态增强算法实战解析