手写Mybatis-01
主要分成三部分
- 用户定义的数据库操作接口(Dao层)
- xml配置的sql语句
- 数据库
代理可以封装一个复杂的流程为接口对象的实现类。

1. MapperProxy代理类
这是一个动态代理类,用于代理接口方法调用。通过 InvocationHandler 接口实现对目标接口方法的拦截与处理。
核心功能:
- 使用
Map<String, String>存储接口方法名与 SQL 语句的映射关系。 - 动态代理接口方法调用,并根据接口名和方法名查找对应的 SQL 语句。
public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -1047155665507002273L;
/** * 存储mapper的sql语句对应的key-value * key: mapper的类名+方法名 * value: sql语句 */ private Map<String, String> sqlSession;
/** * mapper的接口类型,当前代理对象代理的接口 */ public final Class<T> mapperInterface;
public MapperProxy(Class<T> mapperInterface, Map<String, String> sqlSession) { this.mapperInterface = mapperInterface; this.sqlSession = sqlSession; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } else { return "模拟调用:" + sqlSession.get(mapperInterface.getName() + "." + method.getName()); } }}2. MapperProxyFactory工厂类
MapperProxyFactory 是一个基于简单工厂模式的工具类,用于帮助我们创建动态代理对象。通过封装 Proxy.newProxyInstance 的复杂逻辑,它极大地简化了动态代理对象的创建过程,同时提升了代码的可读性和可维护性
public class MapperProxyFactory<T> { /** *当前工厂类所服务的目标接口 */ private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; }
public T newInstance(Map<String, String> sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<>(mapperInterface, sqlSession); return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy); }}3. IUserDao接口,被代理的接口
public interface IUserDao { String getUserInfoById(String id);}4. 测试
使用MapperProxyFactory创建 IUserDao 接口的动态代理对象,
public static void main(String[] args) { MapperProxyFactory<IUserDao> mapperProxyFactory = new MapperProxyFactory<>(IUserDao.class); Map<String, String> sqlSession = new HashMap<>(); sqlSession.put("test.dao.IUserDao.getUserInfoById", "模拟执行 Mapper.xml 中 SQL 语句的操作:根据id查找用户信息");
IUserDao iUserDao = mapperProxyFactory.newInstance(sqlSession); String userInfoById = iUserDao.getUserInfoById("12"); System.out.println(userInfoById); }
5. 总结
目前实现了一个简易版本的Mybatis,其中使用代理类工厂把代理的创建给封装起来了,避免每次创建代理类操作都要创建一个新的代理对象。
此小结学习了:
- 代理的使用
- 工厂设计模式
评论