详解反射机制和动态代理原理

详解反射机制和动态代理原理

1. 反射是什么

反射:是基于反射分析类的信息,然后获取到类/成员变量/成员方法/成员方法的参数

2. 代码举例

普通创建对象

1
2
3
User user = new User();
user.setUserName("李四");
user.setAge(20);

反射创建对象

1
2
3
4
5
6
Class<?> clazz = Class.forName("com.oimc.aimin.test.entity.User");
Object obj = clazz.getDeclaredConstructor().newInstance();

Field field = clazz.getDeclaredField("userName");
field.setAccessible(true);
field.set(obj, "李四");

普通创建对象是“编译期确定类”,反射是“运行期动态确定类”

  • 普通创建对象:类在编译期已经写死
  • 反射创建对象:类是字符串加载,运行期才知道是哪个类

最关键的区别:“能不能提前知道类是谁”

普通new:你必须提前知道类

1
User user = new User();
  • 编译器必须能找到 User.class
  • 如果你删了 User,项目直接编译失败

反射:类是“运行时加载”的

1
Class.forName("com.xxx.User");
  • 编译期根本不知道 User 是否存在
  • 只在程序运行时才去磁盘加载 class
  • 你可以:
    • 配置文件
    • 数据库
    • 网络
    • 动态决定创建哪个类

3. 真实框架场景–Spring 为什么用反射,而不用 new?

当你注册一个bean时,Spring加载这个bean对象的时候使用的反射机制,而不是直接new一个UserService

1
2
@Service
public class UserService {}

因为:
Spring容器启动时根本不知道你会写哪些类!

Spring 做的是:

  1. 扫描包路径 → 找到 UserService.class
  2. 通过反射创建对象
  3. 通过反射注入 @Autowired 的属性
  4. 放入 IOC 容器

如果不用反射:

1
new UserService(); // 那 Spring 就必须提前写死所有类

4. 使用反射的场景

场景 是否必须反射
框架底层(Spring)
IOC / DI 容器
ORM 映射
动态代理
插件化系统
反序列化

5. 反射的优缺点

优点

  • 动态性:打破编译期限制,运行时动态操作类,适合框架开发(无需硬编码类信息)。
  • 灵活性:可适配不同类的通用逻辑(如 ORM 框架的对象映射)。
  • 扩展性:通过反射加载外部类(如插件),增强程序扩展性。

缺点

  • 性能损耗:反射操作绕过编译期优化比直接调用慢 10-100 倍(频繁调用需缓存 Class/Method 对象优化)。
  • 破坏封装:setAccessible(true) 可访问私有成员,违反类的封装设计。

6. 动态代理

动态代理的实现

动态代理是在运行时通过反射机制生成代理对象,在不修改目标类源码的前提下,对方法进行增强

1
2
业务类:只负责业务
代理类:统一负责事务 / 日志 / 权限

JDK 动态代理完整示例

在不修改 UserServiceImpl 源码的前提下,为 addUser() 方法自动添加“开启事务 + 提交事务”的增强逻辑

1️⃣ 定义接口(必须有接口)

1
2
3
public interface UserService {
void addUser();
}

2️⃣ 真实实现类(被代理的目标对象)

1
2
3
4
5
6
7
public class UserServiceImpl implements UserService {

@Override
public void addUser() {
System.out.println("执行业务:添加用户");
}
}

3️⃣ 创建动态代理(核心)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyTest {

public static void main(String[] args) {

// 目标对象
UserService target = new UserServiceImpl();

// 生成代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(), // 类加载器
target.getClass().getInterfaces(), // 实现的接口
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("【开启事务】");
Object result = method.invoke(target, args); // 调用真实方法
System.out.println("【提交事务】");

return result;
}
}
);

// 调用代理方法
proxy.addUser();
}
}

4️⃣ 运行结果

有动态代理:

1
2
3
【开启事务】
执行业务:添加用户
【提交事务】

没有动态代理:

1
执行业务:添加用户

7. 动态代理 vs 反射 vs 普通 new

技术 作用
new 创建“真实对象”
反射 运行时“操作对象”
动态代理 运行时“生成增强对象”

动态代理 = 反射的高级形态

END