框架专题:反射
1. 什么是反射?
简单来说,反射是一种程序自省的能力,即在程序运行时动态地获取其结构信息或操作其行为。这包括类、方法、属性等元信息。反射的核心在于让代码变得更加动态化,从而突破静态语言的限制。
以Java为例,反射允许你:
- 动态获取一个类的名称、字段、方法、构造函数等信息;
- 创建类的实例;
- 调用类的方法或访问类的字段;
- 修改类的行为。
示例代码
以下是一段使用Java反射的示例代码:
import java.lang.reflect.Method;public class ReflectionDemo {public static void main(String[] args) throws Exception {Class<?> clazz = Class.forName("java.util.ArrayList");Object instance = clazz.getDeclaredConstructor().newInstance();Method addMethod = clazz.getMethod("add", Object.class);addMethod.invoke(instance, "Hello Reflection");System.out.println(instance); // 输出: [Hello Reflection]}
}
在上面的代码中,我们通过反射动态创建了ArrayList
实例,并调用其add
方法加入了一个元素。
2. 为什么要使用反射?
反射的主要作用体现在以下几个方面:
2.1 提高代码灵活性
反射允许框架开发者编写能够适配不同需求的通用代码。例如,在ORM(对象关系映射)框架中,可以通过反射动态解析实体类和数据库表的映射关系。
2.2 动态加载和执行代码
反射使程序能够在运行时根据用户需求加载不同的模块或插件,而无需提前知道它们的具体实现。例如,Spring框架通过反射动态创建和管理Bean对象。
2.3 元编程能力
反射为程序提供了操作自身结构的能力,从而实现高效的工具开发,如动态代理、注解处理器等。
3. 反射的典型使用场景
3.1 框架开发
几乎所有的主流框架都离不开反射的使用。以下是几个典型应用:
- Spring:通过反射动态扫描类路径,加载符合条件的Bean;
- Hibernate:通过反射解析实体类的注解,生成SQL语句。
- MyBatis:MyBatis 大量使用反射技术来实现以下功能:
- SQL语句的动态解析:通过反射读取Mapper接口中定义的方法信息,将其与SQL映射文件的内容动态绑定。
- 结果映射:通过反射将查询结果的字段值动态注入到目标实体类的属性中。
- 方法代理:利用动态代理和反射技术,实现Mapper接口的方法调用与底层执行逻辑的解耦。
3.2 插件机制
插件机制的实现依赖于程序能够动态加载和调用未知模块。例如,浏览器可以通过反射加载第三方插件。
3.3 动态代理
Java的Proxy
类和C#的DynamicObject
都依赖于反射实现动态代理,常用于AOP(面向切面编程)。
4. 反射的实际案例分析
案例:自定义注解解析
假设我们需要开发一个简单的框架,通过注解实现方法权限检查。
步骤1:定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiresPermission {String value();
}
步骤2:编写目标类
public class UserService {@RequiresPermission("admin")public void deleteUser() {System.out.println("User deleted");}public void addUser() {System.out.println("User added");}
}
步骤3:实现注解解析逻辑
import java.lang.reflect.Method;public class PermissionChecker {public static void checkPermissions(Object object) throws Exception {Method[] methods = object.getClass().getMethods();for (Method method : methods) {if (method.isAnnotationPresent(RequiresPermission.class)) {RequiresPermission annotation = method.getAnnotation(RequiresPermission.class);String requiredPermission = annotation.value();if (!"admin".equals(requiredPermission)) { // 模拟权限检查throw new SecurityException("Permission denied for method: " + method.getName());}method.invoke(object); // 调用方法}}}public static void main(String[] args) throws Exception {UserService userService = new UserService();checkPermissions(userService); // 检查权限并执行方法}
}
输出
如果权限检查通过,deleteUser
方法会被执行;否则抛出权限不足异常。
5. 反射的注意事项
5.1 性能开销
反射操作通常比直接调用慢,主要原因是:
- 缺少编译时优化;
- 方法调用需要额外的安全检查。
因此,在性能敏感的场景下,应尽量避免频繁使用反射。
5.2 安全性风险
反射突破了语言访问控制的限制,可能导致敏感数据被暴露或修改。开发时应严格控制反射操作的权限。
5.3 可维护性
过度依赖反射会增加代码的复杂性和调试难度,应合理权衡其使用场景。
6. 总结
反射是框架开发中不可或缺的工具,为程序提供了运行时的灵活性和动态化能力。通过反射,我们可以实现诸如动态代理、注解处理、插件机制等功能。然而,反射并非万能,开发者在使用时需要权衡性能、安全性和可维护性,以确保代码质量。希望通过本文的介绍,大家能更好地理解和应用反射,为自己的项目增添更多可能性!
相关文章:
框架专题:反射
1. 什么是反射? 简单来说,反射是一种程序自省的能力,即在程序运行时动态地获取其结构信息或操作其行为。这包括类、方法、属性等元信息。反射的核心在于让代码变得更加动态化,从而突破静态语言的限制。 以Java为例,反…...

【Go】context标准库
文章目录 1. 概述1.1 什么是 Context1.2 设计原理1.3 使用场景源码分析核心:Context接口4个实现6个方法TODO 和 BackgroundWithCancelcancelpropagateCancel 绑定父对象WithTimeout 和 WithDeadlineWithValue总结参考1. 概述 基于版本: go1.22.3/src/context/context.go 1.1…...

LLMs之o3:《Deliberative Alignment: Reasoning Enables Safer Language Models》翻译与解读
LLMs之o3:《Deliberative Alignment: Reasoning Enables Safer Language Models》翻译与解读 导读:2024年12月,这篇论文提出了一种名为“审慎式对齐 (Deliberative Alignment)”的新方法,旨在提高大型语言模型 (LLM) 的安全性。论…...
git设置项目远程仓库指向github的一个仓库
要将你的Git项目设置为指向GitHub上的远程仓库,你需要执行以下步骤: 创建GitHub仓库: 登录到你的GitHub账户。点击右上角的 “” 号,选择 “New repository” 创建一个新的仓库。填写仓库的名称,可以添加描述ÿ…...

实战演练JDK的模块化机制
实战演练JDK的模块化机制--楼兰 带你聊最纯粹的Java 你发任你发,我用Java8。你用的JDK到什么版本了?很多开源框架都已经开始陆续升级JDK版本了。你对于JDK8往后陆陆续续更新的这些版本有什么感觉吗? 很多人会说其实并没有太多的感觉。JDK的新版本不断推出一些不痛不痒…...
jdk17+springboot3项目加密部署
最近项目需要在第三方服务器部署,由于没有交付源码。所以需要将项目加密后再部署。 网上找了一圈,发现xjar这个开源项目,可以将代码加密后进行部署。看了下正是我需要的。 于是按照文档打包加密,但启动的时候居然报错。 这个结…...

rm -rf 删除/下bin lib lib64 sbin软链接系统恢复
背景 不小心删除了/bin、/lib、/lib64和/sbin这些目录的软链接,导致系统中的各种命令都无法正常使用。在尝试多种方法后,包括添加环境变量和使用绝对路径执行命令无法恢复,最终不重装完美解决。 [rootcentos-8 /]# ll 总用量 36 drwxr-xr-x …...

并发与竞争
并发与竞争 并发与竞争的产生 Linux是一个多任务操作系统,肯定会存在多个任务共同操作同一段内存或者设备的情况,多个任务甚至中断都能访问的资源叫做共享资源,就和共享单车一样。在驱动开发中要注意对共享资源的保护,也就是要处…...
Java后端开发 ”Bug“ 分享——订单与优惠卷
“优惠券风波”:一段代码引发的线上事故 起因:优惠券功能上线 故事的开始源于公司新上线的一项促销活动——在用户未使用优惠券时,系统会自动赠送一张优惠券。这个功能不仅能提升用户体验,还能拉动平台的销售额。为了赶上活动上…...

Linux系统之tee命令的基本使用
Linux系统之tee命令的基本使用 一、tee命令介绍二、tee命令的使用帮助2.1 tee命令的help帮助2.2 tee命令帮助解释 三、tee命令的基本使用3.1 写入文件3.2 追加文件3.3 结合sudo命令3.4 结合EOF使用 四、注意事项 一、tee命令介绍 tee 是 Linux 和 Unix 系统中的一个命令&#x…...

idea 8年使用整理
文章目录 前言idea 8年使用整理1. 覆盖application配置2. 启动的时候设置编辑空间大小,并忽略最大空间3. 查询类的关系4. 查看这个方法的引用关系5. 查看方法的调用关系5.1. 查看被调用关系5.2. 查看调用关系 6. 方法分隔线7. 选择快捷键类型8. 代码预览插件9. JReb…...

多个微服务 Mybatis 过程中出现了Invalid bound statement (not found)的特殊问题
针对多个微服务的场景,记录一下这个特殊问题: 如果启动类上用了这个MapperScan注解 在resource 目录下必须建相同的 com.demo.biz.mapper 目录结构,否则会加载不到XML资源文件 。 并且切记是com/demo/biz 这样的格式创建,不要使用…...
k8s,service如何找到容器
Kubernetes之所以需要Service,一方面是因为Pod的IP不是固定的,另一方面则是因为一组Pod实例之间总会有负载均衡的需求 被selector选中的Pod,就称为Service的Endpoints,查看方式: kubectl get endpoints hostnames需要…...

观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?
大家好,我是锋哥。今天分享关于【观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?】面试题。希望对大家有帮助; 观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用? 1000道 …...
docker compose deploy fate cluster
官方文档 写的不清晰 KubeFATE,用于生成部署脚本,链接 部署机就是下载了 KubeFATE的主机;运行机就是要安装fate容器的主机(部署机和运行机可以相同) 两个主机:并非必须 centos7,Ubuntu也行Doc…...
字节跳动Java开发面试题及参考答案(数据结构算法-手撕面试题)
怎么判断两个链表是否相交?怎么优化? 判断两个链表是否相交可以采用多种方法。 一种方法是使用双指针。首先分别遍历两个链表,得到两个链表的长度。然后让长链表的指针先走两个链表长度差的步数。之后,同时移动两个链表的指针,每次比较两个指针是否指向相同的节点。如果指…...
网工日记:FTP工作模式
FTP 基本概念 FTP(File Transfer Protocol)即文件传输协议,是用于在网络上进行文件传输的标准协议。它运行在 TCP/IP 协议栈之上,采用客户端 - 服务器(C/S)架构,通过在客户端和服务器之间建立控…...

unity使用代码在动画片段中添加event
unity使用代码在动画片段中添加event using UnityEngine;public static class AnimationHelper {/// <summary>/// 获取Animator状态对应的动画片段/// </summary>/// <param name"animator">Animator组件</param>/// <param name"…...

嵌入式轻量级开源操作系统:HeliOS的使用
嵌入式轻量级开源操作系统:HeliOS的使用 📍项目地址:https://github.com/heliosproj/HeliOS HeliOS项目是一个社区交付的开源项目,用于构建和维护HeliOS嵌入式操作系统(OS)。HeliOS是一个功能齐全的操作系统࿰…...
解决VMware的ubuntu22虚拟机没有网络
解决步骤 1.在 Windows 系统中,按 “WinR” 键,输入 “services.msc” 并回车,在服务列表中找到 “VMware DHCP Service” 和 “VMware NAT Service”,确保这两个服务已启动,若未启动则右键点击选择 “启动”…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...