✅ 动态代理

动态代理 是在程序运行时创建代理对象,不需要提前写好代理类代码。

✅ 本质:用反射机制,在运行时生成代理对象,代理目标对象的方法调用。


✅ 动态代理 vs 静态代理

特性 静态代理 动态代理
编写方式 手动编写代理类 运行时自动生成代理类
灵活性 不够灵活,一个接口一个代理类 很灵活,只需一套代理逻辑
使用场景 小项目、学习 Spring AOP、事务、权限校验等
性能 性能好 性能略低(但可接受)

✅ 动态代理的使用前提

必须基于接口编程!

目标对象要实现一个或多个接口,代理对象也实现这些接口。


✅ 动态代理的基本结构(JDK 实现)

1
2
3
4
5
6
7
8
9
10
11
// 1. 定义接口
public interface UserService {
void login(String username);
}

// 2. 实现类(目标对象)
public class UserServiceImpl implements UserService {
public void login(String username) {
System.out.println(username + " 登录成功!");
}
}

✅ 创建动态代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.lang.reflect.*;

public class ProxyFactory {
public static Object getProxy(Object target) {
return 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;
}
}
);
}
}

✅ 测试使用动态代理

1
2
3
4
5
6
7
8
public class Test {
public static void main(String[] args) {
UserService target = new UserServiceImpl(); // 目标对象
UserService proxy = (UserService) ProxyFactory.getProxy(target); // 获取代理对象

proxy.login("张三"); // 实际调用的是代理对象的方法
}
}

✅ 输出结果

1
2
3
日志:方法开始执行...
张三 登录成功!
日志:方法执行完毕。

✅ 总结动态代理核心知识点

内容 说明
关键类 java.lang.reflect.Proxy
接口 目标对象必须实现接口
回调 使用 InvocationHandler 实现调用逻辑
方法 invoke() 拦截所有接口方法调用

✅ 动态代理常见应用场景

  • Spring AOP 切面(如:事务、日志、安全控制)
  • RPC 框架远程方法调用
  • JDK 和 MyBatis 的代理机制