手写MyBatis第7弹:工厂模式如何解决代理复用问题

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)🔥🔥🔥  有兴趣可以联系我

🔥🔥🔥  文末有往期免费源码,直接领取获取(无删减,无套路)

工厂模式赋能:MyBatis代理对象的诞生之地

  1. 《MyBatis代理工厂解密:SqlSession.getMapper()背后的三层架构》

  2. 《手写MyBatis核心:MapperProxyFactory如何孕育Mapper代理》

  3. 《从接口到实例:深度剖析MyBatis的Mapper代理生成链》

  4. 《SqlSession.getMapper()内部机制:代理工厂模式的完美实践》

  5. 《设计模式在MyBatis的应用:工厂模式如何解决代理复用问题》


代理工厂模式:MyBatis的Mapper生产线

引言: 在MyBatis中,SqlSession.getMapper()如同魔法般将接口转为可执行对象。今天我们将揭开这魔法背后的三层架构,实现Mapper代理的工厂化生产。


一、三层架构实现:从接口到代理实例

核心类关系图

代码实现

1. MapperProxy - 代理逻辑核心

public class MapperProxy implements InvocationHandler {
     private final SqlSession sqlSession;
     private final Class<?> mapperInterface;
     
     public MapperProxy(SqlSession sqlSession, Class<?> mapperInterface) {
         this.sqlSession = sqlSession;
         this.mapperInterface = mapperInterface;
     }
     
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) {
         // 后续将实现SQL执行
         System.out.println("代理方法: " + method.getName());
         return null;
     }
 }

2. MapperProxyFactory - 代理对象工厂

public class MapperProxyFactory<T> {
    private final Class<T> mapperInterface;
    // 工厂缓存:避免重复创建相同接口的工厂
    private static final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
    
    public MapperProxyFactory(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }
    
    // 获取工厂实例(缓存优化)
    public static <T> MapperProxyFactory<T> getInstance(Class<T> mapperInterface) {
        return (MapperProxyFactory<T>) knownMappers.computeIfAbsent(
            mapperInterface, 
            clazz -> new MapperProxyFactory<>(clazz)
        );
    }
    
    // 创建代理对象
    public T newInstance(SqlSession sqlSession) {
        final MapperProxy proxy = new MapperProxy(sqlSession, mapperInterface);
        return (T) Proxy.newProxyInstance(
            mapperInterface.getClassLoader(),
            new Class[]{mapperInterface},
            proxy
        );
    }
}

3. SqlSession实现 - 用户入口

public class DefaultSqlSession implements SqlSession {
     private final Configuration configuration;
     
     public DefaultSqlSession(Configuration configuration) {
         this.configuration = configuration;
     }
     
     @Override
     public <T> T getMapper(Class<T> type) {
         // 从配置中获取Mapper接口的工厂
         MapperProxyFactory<T> factory = configuration.getMapperFactory(type);
         return factory.newInstance(this);
     }
 }

二、工厂模式的价值解析

为什么需要MapperProxyFactory?
问题无工厂方案工厂方案
对象复用每次getMapper创建新代理缓存代理实例
资源消耗重复生成字节码减少字节码生成开销
配置解耦代理创建逻辑侵入SqlSession创建逻辑封装隔离
扩展性添加新功能需修改入口类可扩展工厂行为
SqlSession.getMapper()的核心作用
  1. 统一入口:用户获取Mapper的唯一标准方式

  2. 生命周期管理:绑定到当前SqlSession

  3. 资源整合:传递配置信息和数据库连接

  4. 类型安全:编译期检查接口类型


三、深度思考:工厂模式的设计哲学

三级缓存优化体系
  1. MapperProxyFactory缓存 knownMappers避免重复创建相同接口的工厂

  2. 代理实例缓存(可选扩展)

    public class MapperProxyFactory<T> {
         private T proxyInstance; // 单例代理
         
         public synchronized T newInstance(SqlSession sqlSession) {
             if (proxyInstance == null) {
                 proxyInstance = createProxy(sqlSession);
             }
             return proxyInstance;
         }
     }
  3. MapperMethod缓存MapperProxy中缓存方法对应的执行逻辑

MyBatis的工厂模式变体

设计原则体现
  1. 单一职责原则

    • SqlSession:提供操作入口

    • MapperProxyFactory:专注代理创建

    • MapperProxy:处理方法调用

  2. 开闭原则 新增Mapper接口无需修改工厂逻辑


结语: MapperProxyFactory作为MyBatis代理体系的核心枢纽,通过工厂模式将复杂的代理创建过程封装简化。这种设计不仅提升了性能,更为框架的扩展性奠定了坚实基础。


往期免费源码 (无删减,无套路):🔥🔥🔥  

https://pan.baidu.com/s/1sjAr08PU9Xe7MQf1gjGM5w?pwd=6666​

「在线考试系统源码(含搭建教程)」 (无删减,无套路):🔥🔥🔥  

链接:https://pan.quark.cn/s/96c4f00fdb43 提取码:WR6M

往期免费源码对应视频:

免费获取--SpringBoot+Vue宠物商城网站系统

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值