在 MyBatis 中,代理对象是通过动态代理技术生成的对象,用于拦截对接口方法的调用并将这些调用转发给相应的 SQL 映射文件中的 SQL 语句执行。具体来说,代理对象是一个实现了某个接口的类实例,但这个实例的实际行为是在运行时动态生成的,而不是在编译时固定的。
### 动态代理
在 Java 中,动态代理通常通过 `java.lang.reflect.Proxy` 类和 `InvocationHandler` 接口来实现。MyBatis 使用了这种机制来生成 Mapper 接口的代理对象。
### 代理对象的工作原理
1. **接口定义**:
定义一个 Mapper 接口,如 `UserMapper`。
```java
public interface UserMapper {
User getUserById(int id);
}
```
2. **MapperFactoryBean 创建代理对象**:
当 MyBatis 初始化时,`MapperFactoryBean` 会为每个 Mapper 接口创建一个代理对象。这个代理对象实现了 `UserMapper` 接口。
3. **代理对象拦截方法调用**:
当你通过代理对象调用 `getUserById` 方法时,实际的调用会被代理对象拦截。
4. **调用转换**:
代理对象会将拦截到的方法调用转换为对相应 SQL 映射文件中的 SQL 语句的调用。具体步骤包括:
- 查找与方法名匹配的 SQL 语句(如 XML 配置文件中的 `<select>` 语句)。
- 将方法参数传递给 SQL 语句。
- 执行 SQL 语句。
- 将 SQL 执行结果映射为方法的返回类型(如 `User` 对象)。
### 代理对象的示例
以下是一个使用动态代理的简单示例,以帮助理解代理对象的概念。
```java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义接口
interface UserMapper {
User getUserById(int id);
}
// 模拟 User 对象
class User {
private int id;
private String name;
// getters and setters
}
// 实现 InvocationHandler
class MapperInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这里可以添加对方法调用的拦截逻辑
System.out.println("Method " + method.getName() + " is called with args " + args[0]);
// 模拟返回结果
User user = new User();
user.setId((int) args[0]);
user.setName("John Doe");
return user;
}
}
public class Main {
public static void main(String[] args) {
// 创建代理对象
UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(
UserMapper.class.getClassLoader(),
new Class[]{UserMapper.class},
new MapperInvocationHandler()
);
// 调用代理对象的方法
User user = userMapper.getUserById(1);
System.out.println("User: " + user.getName());
}
}
```
在这个示例中:
- `UserMapper` 是一个接口。
- `MapperInvocationHandler` 实现了 `InvocationHandler` 接口,定义了如何处理方法调用。
- 使用 `Proxy.newProxyInstance` 创建了一个 `UserMapper` 接口的代理对象。
- 当调用 `userMapper.getUserById` 方法时,实际的调用被 `MapperInvocationHandler` 拦截并处理。
在 MyBatis 中,类似的机制被用来拦截对 Mapper 接口方法的调用,并将这些调用转换为对 SQL 映射文件的操作。通过这种方式,MyBatis 实现了将 Java 方法调用与 SQL 语句执行的无缝集成。
标签:调用,对象,UserMapper,代理,技术,User,SQL,mybatis From: https://www.cnblogs.com/zqlmianshi/p/18421063