静态代理
一、什么是代理(Proxy)?
代理的意思很简单:
"不让你直接找目标对象,而是通过中间人(代理)去访问。"
就像明星不直接接电话,而是通过经纪人(代理人)来沟通。
🧱 二、一个最简单的例子(静态代理)
我们先写一个接口 和一个真正干活的类:
csharp
// 抽象主题(接口)
public interface UserService {
void addUser();
}
// 真实主题(被代理类)
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("执行添加用户的逻辑");
}
}
现在我们想在执行 addUser()
之前打印日志。 如果你直接改 UserServiceImpl
,就破坏了它的纯净性。
于是我们写一个「代理类」👇
🤵 三、静态代理类实现
csharp
// 代理类
public class UserServiceProxy implements UserService {
private UserService target; // 持有真实对象的引用
public UserServiceProxy(UserService target) {
this.target = target;
}
@Override
public void addUser() {
System.out.println("前置操作:开始记录日志");
target.addUser(); // 调用目标对象的方法
System.out.println("后置操作:操作成功");
}
}
🚀 四、使用
java
public class Test {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxy = new UserServiceProxy(userService);
proxy.addUser();
}
}
动态代理(将接口代理出去,实现这个接口的调用方法,都会执行代理内部的方法)
动态代理的核心就是在内存中动态生成一个代理类,这个类实现了指定接口,所有方法调用最终都会转发到 InvocationHandler 的 invoke() 方法中。
"定义一个接口 → 动态生成代理类实现接口 → 通过反射执行 SQL 并返回结果"
在手写mybatis-plus源码中如何实现
定义一个通用接口,这个接口里面有增删改查泛型,然后里面的所有都会被代理
然后的话先把继承这个接口的都进行代理,这样内部调用的方法都会通过调用反射的sql来实现
核心方法
loader
:类加载器,用来加载生成的代理类;
interfaces
:要实现的接口(比如 UserMapper);
h
:你的回调处理器,实现了 InvocationHandler
接口。
vbnet
public static Object newProxyInstance(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
}
阶段 | 做的事 | 技术点 |
---|---|---|
1️⃣ 接口定义 | 定义 BaseMapper<T> |
泛型接口 |
2️⃣ 获取代理 | getMapper(UserMapper.class) |
JDK 动态代理 |
3️⃣ 调用方法 | 调用 selectById() |
反射调用 invoke() |
4️⃣ 解析方法 | 找到对应 SQL 映射 | 反射+缓存 |
5️⃣ 执行 SQL | 调用 JDBC 执行 SQL | SQLSession |
6️⃣ 封装结果 | 将结果封装为 T 类型 |
泛型+反射 |