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

Java 反射、注解、代理详解:一篇搞懂这三个核心概念

Java 反射、注解、代理详解:一篇搞懂这三个核心概念

前言

博主计划使用CSDN来记录Java后端开发的学习经历,并分享自己的编程心得和知识,期望能为那些有需求的朋友提供帮助。
博主也期望能与那些持续努力学习的朋友们共同进步!编程之路是一条充满艰辛与挑战的路,需要我们付出更多的心血,才能走得更远。只有通过不懈的研究和深入的思考,以及勤于实践,我们才能在编程的道路上取得真正的成就


一、反射:运行期间动态获取类信息

什么是反射?

简单说:在程序运行期间,动态获取类的信息(构造器、成员变量、方法等),并且能够创建类的对象。

获取 Class 对象的三种方式

// 1. 类名.classClasscatClass=Cat.class;// 2. Class.forName()ClasscatClass2=Class.forName("com.itheima.reflect.Cat");// 3. 对象.getClass()ClasscatClass3=newCat().getClass();

重点:同一个类的 Class 对象有且只有一份。

获取构造器

// 获取全部 public 构造器Constructor[]constructors1=catClass.getConstructors();// 获取全部构造器(包括 private)Constructor[]constructors2=catClass.getDeclaredConstructors();// 获取特定构造器Constructorconstructor=catClass.getConstructor(Integer.class);// 获取 private 构造器Constructorconstructor3=catClass.getDeclaredConstructor(String.class);constructor3.setAccessible(true);// 必须打开权限

获取成员变量

// 获取所有 public 成员变量Field[]fields1=catClass.getFields();// 获取所有成员变量(包括 private)Field[]fields2=catClass.getDeclaredFields();// 获取指定成员变量Fieldfield=catClass.getDeclaredField("name");field.setAccessible(true);field.set(cat1,"小红");

获取成员方法

// 获取所有 public 方法Method[]methods1=catClass.getMethods();// 获取所有方法(包括 private)Method[]methods2=catClass.getDeclaredMethods();// 执行方法Methodmethod=catClass.getMethod("getName");Stringres=(String)method.invoke(cat1);

反射的作用

  • 框架开发(Spring、MyBatis 等)
  • 动态代理
  • 绕过泛型检查
  • 序列化/反序列化

二、注解:让代码"说话"

什么是注解?

注解就是 Java 代码里的特殊标记,比如@Override@Deprecated等。

作用:让其他程序根据注解信息来决定怎么执行该程序。

注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上等位置。

自定义注解

@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})@Inherited// 如果有子类,则可以继承这个类的注解public@interfaceMyTest1{Stringaaa()default"aaa";booleanbbb()defaulttrue;String[]ccc()default{"a","b","c"};}

元注解:注解的注解

主要分为两种:

元注解作用
@Target指定注解可以用在哪些位置
@Retention指定注解保留到什么时候(源码/类文件/运行时)

解析注解

// 获取类上的所有注解Annotation[]annotations=Dog.class.getDeclaredAnnotations();// 获取指定注解MyTest1annotation=Dog.class.getDeclaredAnnotation(MyTest1.class);// 判断是否存在某个注解booleanexists=Dog.class.isAnnotationPresent(MyTest1.class);// 获取成员变量上的注解FieldnameField=Dog.class.getDeclaredField("name");MyTest1fieldAnnotation=nameField.getDeclaredAnnotation(MyTest1.class);

三、代理:对方法功能进行增强

什么是代理?

代理就是可以对对象的某些方法的功能进行增强,而且一般是和原本逻辑不太相关的增强。

应用场景

  • 日志记录
  • 事务管理
  • 权限控制
  • 性能监控

核心概念

概念说明
目标对象需要被增强的对象
目标类需要被增强的类
代理对象增强之后的对象
代理类增强之后的类

静态代理

两种方式

  1. 继承父类:创建子类继承目标类,重写方法进行增强
  2. 实现接口:新建实现类实现相同接口,内部持有目标对象引用

继承父类示例

publicclassInheritedProxyextendsStar{privateStarstar;publicInheritedProxy(Starstar){this.star=star;}@Overridepublicvoidsing(){System.out.println("收钱");star.sing();}}

实现接口示例

publicclassImplementProxyimplementsStartInterface{privateStartInterfacestar;publicImplementProxy(StartInterfacestar){this.star=star;}@Overridepublicvoidsing(){System.out.println("收钱");star.sing();}}

缺点:针对每一个需要被增强的目标类都需要手写一个代理类,如果有很多目标类都需要增强同一个逻辑,会非常麻烦。

动态代理(推荐)

动态代理技术有好几种:

类型原理适用场景
JDK 动态代理基于实现接口目标类要有实现接口
CGLIB基于继承父类(ASM 字节码)只要是一个类都可以

核心区别

  • 静态代理:编译阶段已经生成代理类
  • 动态代理:程序运行过程中才生成代理类

项目中更推荐使用动态代理

JDK 动态代理示例

InvocationHandler 实现

publicclassStarInvocationHandlerimplementsInvocationHandler{privateStartInterfacetarget;publicStarInvocationHandler(StartInterfacetarget){this.target=target;}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{System.out.println("收钱");Objectresult=method.invoke(target,args);returnresult;}}

使用方式

Starstar=newStar();StartInterfacestarProxy=(StartInterface)Proxy.newProxyInstance(star.getClass().getClassLoader(),star.getClass().getInterfaces(),newStarInvocationHandler(star));starProxy.sing();

newProxyInstance 执行流程

  1. 生成远程.java源程序文件
  2. 使用 JDK 编译javac生成字节码文件.class
  3. 使用类加载器加载到内存

写在最后

反射、注解、代理这三个概念,是 Java 框架开发的基石。

  • 反射让你能动态操作类
  • 注解让代码自带"说明书"
  • 代理让你能无侵入地增强功能

学的时候可能觉得抽象,但用多了就会发现:这玩意儿真的香。

Spring、MyBatis、Spring Boot… 这些主流框架底层都在用。

建议:先把基础概念搞懂,然后多看看框架源码,理解会更深。


👉源码参考:文中代码示例可参考com.itheima.reflect

http://www.jsqmd.com/news/561406/

相关文章:

  • 2026年论文党必备:盘点2026年当红之选的一键生成论文工具
  • 高效客户开发:摆脱低效推销,低成本稳定获客
  • AT_arc206_d [ARC206D] LIS ∩ LDS
  • 微信聊天记录永久保存:WeChatMsg带来的3大突破,让珍贵对话不再丢失
  • 为什么越来越多的STM32项目转向HAL库?从寄存器封装层次看开发效率提升
  • 别再瞎找了!盘点2026年口碑爆棚的一键生成论文工具
  • SpringBoot集成JPA与人大金仓Kingbase:从踩坑到部署的实战指南
  • Web学习笔记二:HTML基础实操
  • APK Installer:在Windows上直接安装Android应用的革命性方案
  • 2026年AI智能无损选果机产品有哪些,冬枣分选机/水果分选机/无损测糖选果机/无损分选机,AI智能无损选果机企业哪家好 - 品牌推荐师
  • HttpServlet知识总结
  • MySQL排序性能瓶颈解析:从Filesort到索引优化的实战策略
  • 单电源差分放大电路设计实战解析
  • macOS效率工具:Dozer极简菜单栏管理方案
  • 论文AI率降不到20%?找到症结再攻克的完整攻略
  • 写作压力小了!盘点2026年标杆级的AI论文网站
  • [特殊字符]OpenClaw 优化系列(二):飞书工作助手“调教”思路和详细过程,纯干货,可抄作业!!!
  • [2026钉耙热身]拉马努金解算法题
  • 别再手动点打印了!用Electron + Vue3给你的Web应用加上‘一键静默打印’功能
  • Steamauto架构深度解析:多平台自动化交易引擎的技术实现
  • 2026最新珠三角塑胶合模线打磨厂商推荐!广东优质自动化服务商权威榜单 - 十大品牌榜
  • 从零开始掌握Retrieval-based Voice Conversion WebUI:AI语音转换完整指南
  • 2026家装新趋势:半包装修选哪家品牌更靠谱?定制整体全屋,专业团队保障装修质量 - 品牌推荐师
  • OpenClaw:WSL2中安装与配置
  • 项目实训个人工作记录一
  • FetchDataLogic-国标视频平台信令服务器统一定时数据获源码实现
  • OpenClaw+GLM-4.7-Flash:个人财务管理自动化实践
  • P1036 [NOIP 2002 普及组] 选数
  • Qwen-Image-Edit-F2P模型安全:Token身份认证机制设计
  • 深入J-Link RTT缓冲区:从阻塞/非阻塞模式选择到彩色日志打印的进阶玩法