JavaSE—反射与动态代理

好的,我们来做一个 JavaSE 进阶专题:反射(Reflection)与动态代理(Dynamic Proxy) 全面解析,从原理、用法到实战场景,让你不仅会用,还能理解背后的机制。


1. Java 反射(Reflection)

1.1 反射概念

反射是 Java 在运行时获取类信息并操作类对象的能力,可以实现:

  • 获取类的 结构信息:类名、方法、字段、构造器
  • 动态创建对象
  • 动态调用方法和修改字段
  • 在运行时实现灵活的框架设计(如依赖注入、ORM)

1.2 核心类

功能
Class<?>获取类信息
Field访问属性
Method调用方法
Constructor创建对象
Modifier获取访问修饰符

1.3 基本用法示例

Class<?> clazz = Class.forName("com.example.User");

// 创建对象
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object user = constructor.newInstance("Alice", 18);

// 访问字段
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true); // 访问私有字段
nameField.set(user, "Bob");

// 调用方法
Method printMethod = clazz.getDeclaredMethod("printInfo");
printMethod.invoke(user);

特点

  • 可以操作 私有成员
  • 动态调用,无需在编译期知道具体类
  • 常用于框架、工具类(如 Spring、MyBatis、JUnit)

1.4 注意事项

  • 性能:反射比普通调用慢
  • 安全:需要考虑 setAccessible(true) 的访问权限
  • 类型安全:反射绕过编译检查,需要小心类型转换

2. Java 动态代理(Dynamic Proxy)

2.1 动态代理概念

动态代理是 在运行时创建接口实现类,并通过 InvocationHandler 控制方法执行。
适用场景:

  • AOP(切面编程)
  • 日志记录、权限控制
  • RPC 框架实现

2.2 JDK 动态代理

核心类/接口

类/接口功能
Proxy生成代理对象
InvocationHandler方法调用处理器

示例

interface UserService {
    void addUser(String name);
}

class UserServiceImpl implements UserService {
    public void addUser(String name) {
        System.out.println("Adding user: " + name);
    }
}

// 动态代理
UserService proxy = (UserService) Proxy.newProxyInstance(
    UserService.class.getClassLoader(),
    new Class[]{UserService.class},
    (proxyObj, method, args) -> {
        System.out.println("Before method: " + method.getName());
        Object result = method.invoke(new UserServiceImpl(), args);
        System.out.println("After method: " + method.getName());
        return result;
    }
);

proxy.addUser("Alice");

输出:

Before method: addUser
Adding user: Alice
After method: addUser

特点

  • 代理类在运行时生成
  • 只代理接口(JDK Proxy)
  • 方法调用可统一处理(切面)

2.3 CGLIB 动态代理

  • CGLIB 通过继承目标类生成代理类
  • 可以代理 非接口类
  • 常用于 Spring AOP(类级别代理)

2.4 动态代理应用场景

  1. 日志记录:方法调用前后打印日志
  2. 权限检查:方法执行前判断权限
  3. 事务管理:方法执行前开启事务,执行后提交/回滚
  4. RPC 框架:接口调用通过代理远程执行

3. 反射与动态代理联系

特性反射动态代理
本质操作类和对象创建接口实现类并控制方法调用
运行时可动态获取类信息并操作可动态拦截方法调用
应用框架初始化、对象注入AOP、日志、RPC
性能较慢比普通方法慢,但比多次反射调用快(方法统一处理)

4. 高效使用方法论

  1. 仅在框架或工具层使用反射,业务代码尽量直接调用
  2. 缓存反射对象(Class、Method、Field),避免重复查找
  3. 动态代理处理切面逻辑,业务方法保持纯净
  4. 必要时使用 CGLIB,代理类或非接口类
  5. 性能监控:频繁调用场景注意代理和反射开销

💡 总结

  • 反射 = 动态操作类、对象、方法
  • 动态代理 = 动态生成接口实现并拦截方法调用
  • 两者结合是 Java 框架(Spring、MyBatis)核心机制

我可以帮你画一张 Java 反射 + 动态代理原理图,展示 类信息获取 → 方法调用 → 动态代理拦截流程,让理解更直观。

你希望我画吗?

文章已创建 5021

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部