反射和设计模式

一、反射(Reflection)深度解析

反射是程序运行时自省自身结构的能力,核心是打破编译期的类型绑定,实现动态操作类或对象的成员。

  1. 核心功能
  • 动态获取类的元数据:包括类名、父类、接口、属性、方法、注解等信息。

  • 动态创建对象:无需通过 new 关键字,直接通过类的全限定名实例化对象。

  • 动态调用成员:可调用对象的任意方法(包括私有方法)、访问任意属性(包括私有属性)。

  • 动态修改访问权限:通过 setAccessible(true) 突破 Java 等语言的访问修饰符限制。

  1. 典型应用场景
  • 框架开发:Spring 的 IOC 容器通过反射扫描注解、创建 Bean 实例;MyBatis 通过反射映射数据库结果集到实体类。

  • 动态代理:JDK 动态代理基于反射实现,为目标类生成代理对象并增强方法。

  • 序列化与反序列化:JSON 工具(如 Jackson)通过反射读取对象属性并转换为 JSON 字符串,反之亦然。

  1. 优缺点
  • 优点:极大提升代码灵活性,降低模块间耦合,适配多变的业务需求。

  • 缺点:破坏封装性、降低代码可读性;运行时解析元数据会产生性能开销;绕过编译期检查,易引发运行时异常。

二、设计模式深度解析

设计模式是软件开发中经验证的可复用解决方案,针对特定场景下的通用问题,遵循"高内聚、低耦合"的设计原则,分为三大类共 23 种经典模式。

  1. 三大分类及核心模式

分类 核心目标 典型模式 应用场景举例

创建型 封装对象的创建过程 单例、工厂方法、抽象工厂、建造者、原型 Spring Bean 单例管理、数据库连接池

结构型 优化类或对象的组合结构 适配器、装饰器、代理、桥接、组合 日志框架的装饰器扩展、MyBatis 动态代理

行为型 协调类或对象间的交互逻辑 观察者、策略、模板方法、迭代器、责任链 事件监听机制、排序算法策略切换

  1. 设计模式的核心原则
  • 开闭原则:对扩展开放,对修改关闭。

  • 依赖倒置原则:依赖抽象而非具体实现。

  • 单一职责原则:一个类只负责一个功能模块。

  • 里氏替换原则:子类可无缝替换父类且不影响程序运行。

三、反射与设计模式的结合应用

反射为设计模式的实现提供了动态化支撑,能简化模式的代码逻辑,提升其灵活性,以下是典型结合场景:

  1. 反射 + 工厂模式
  • 传统工厂模式需硬编码判断逻辑,新增产品类时必须修改工厂类,违反开闭原则。

  • 结合反射后,可通过配置文件 + 反射动态创建产品对象:将产品类的全限定名配置在 properties 或 xml 中,工厂类读取配置后通过反射实例化对象,新增产品时仅需修改配置,无需改动工厂代码。

  • 示例(Java):

java

// 读取配置文件获取类名

String className = PropertiesUtil.getProperty("product.class");

// 反射创建对象

Class<?> clazz = Class.forName(className);

Product product = (Product) clazz.newInstance();

  1. 反射 + 策略模式
  • 策略模式定义算法族并封装,让算法可互相替换,但传统方式需手动维护策略对象的创建。

  • 结合反射后,可通过注解标记策略类,程序启动时扫描所有策略类并通过反射实例化,存入策略容器,后续直接从容器中获取策略对象执行。

  1. 反射 + 动态代理模式
  • JDK 动态代理的核心是 InvocationHandler 接口,其 invoke 方法通过反射调用目标对象的方法,并在调用前后添加增强逻辑(如日志、事务、权限校验)。

  • 示例核心逻辑:

java

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// 前置增强:如记录日志

System.out.println("方法执行前:" + method.getName());

// 反射调用目标方法

Object result = method.invoke(target, args);

// 后置增强:如事务提交

System.out.println("方法执行后:" + method.getName());

return result;

}

四、结合使用的注意事项

  1. 控制反射的使用范围:仅在框架底层或动态化需求场景使用,业务代码中尽量避免,减少性能损耗。

  2. 缓存反射元数据:多次获取同一个类的 Class 对象或 Method 对象时,可缓存起来,避免重复解析元数据。

  3. 避免破坏封装:非必要不通过反射访问私有成员,优先使用公开 API 交互。

相关推荐
一定要AK2 小时前
Spring 入门核心笔记
java·笔记·spring
A__tao2 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
KevinCyao2 小时前
java视频短信接口怎么调用?SpringBoot集成视频短信及回调处理Demo
java·spring boot·音视频
迷藏4942 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
wuxinyan1233 小时前
Java面试题47:一文深入了解Nginx
java·nginx·面试题
新知图书3 小时前
搭建Spring Boot开发环境
java·spring boot·后端
冰河团队3 小时前
一个拉胯的分库分表方案有多绝望?整个部门都在救火!
java·高并发·分布式数据库·分库分表·高性能
洛_尘3 小时前
Java EE进阶:Linux的基本使用
java·java-ee
宸津-代码粉碎机3 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
MaCa .BaKa4 小时前
47-心里健康咨询平台/心理咨询系统
java·spring boot·mysql·tomcat·maven·intellij-idea·个人开发