一、前言:小镇卷码家
总有不少研发伙伴问小傅哥:“为什么学设计模式、看框架源码、补技术知识,就一个普通的业务项目,会造飞机不也是天天写CRUD吗?”
你说的没错,但你天天写CRUD,你觉得 烦不? 慌不? 是不是既担心自己没有得到技术成长,也害怕将来没法用这些都是CRUD的项目去参加;述职、晋升、答辩,甚至可能要被迫面试时,自己手里一点干货也没有的情况。
所以你/我作为一个 小镇卷码家 ,当然要扩充自己的知识储备,否则 架构,架构思维不懂
、 设计,设计模式不会
、 源码、源码学习不深
,最后就用一堆CRUD写简历吗?
二、源码:学设计模式
在 Mybatis 两万多行的框架源码实现中,使用了大量的设计模式来解耦工程架构中面对复杂场景的设计,这些是设计模式的巧妙使用才是整个框架的精华, 这也是小傅哥喜欢卷源码的重要原因 。经过小傅哥的整理有如下10种设计模式的使用,如图所示
讲道理,如果只是把这10种设计模式背下来,等着下次面试的时候拿出来说一说,虽然能有点帮助,不过这种学习方式就真的算是把路走窄了。就像你每说一个设计模式,能联想到这个设计模式在Mybatis的框架中,体现到哪个流程中的源码实现上了吗?这个源码实现的思路能不能用到你的业务流程开发里? 别总说你的流程简单,用不上设计模式!难到因为有钱、富二代,就不考试吗?
好啦,不扯淡了,接下来小傅哥就以 《手写Mybatis:渐进式源码实践》 的学习,给大家列举出这10种设计模式,在Mybatis框架中都体现在哪里了!
三、类型:创建型模式
1. 工厂模式
源码详见: cn.bugstack.mybatis.session.SqlSessionFactory
public interface SqlSessionFactory { SqlSession openSession(); }
源码详见: cn.bugstack.mybatis.session.defaults.DefaultSqlSessionFactory
public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; } @Override public SqlSession openSession() { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); TransactionFactory transactionFactory = environment.getTransactionFactory(); tx = transactionFactory.newTransaction(configuration.getEnvironment().getDataSource(), TransactionIsolationLevel.READ_COMMITTED, false); // 创建执行器 final Executor executor = configuration.newExecutor(tx); // 创建DefaultSqlSession return new DefaultSqlSession(configuration, executor); } catch (Exception e) { try { assert tx != null; tx.close(); } catch (SQLException ignore) { } throw new RuntimeException("Error opening session. Cause: " + e); } } }
- 工厂模式 :简单工厂,是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例对象的类型。
- 场景介绍 :
SqlSessionFactory
是获取会话的工厂,每次我们使用 Mybatis 操作数据库的时候,都会开启一个新的会话。在会话工厂的实现中负责获取数据源环境配置信息、构建事务工厂、创建操作SQL的执行器,并最终返回会话实现类。 - 同类设计 :
SqlSessionFactory
、ObjectFactory
、MapperProxyFactory
、DataSourceFactory
2. 单例模式
源码详见: cn.bugstack.mybatis.session.Configuration
public class Configuration { // 缓存机制,默认不配置的情况是 SESSION protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION; // 映射注册机 protected MapperRegistry mapperRegistry = new MapperRegistry(this); // 映射的语句,存在Map里 protected final Map<String, MappedStatement> mappedStatements = new HashMap<>(); // 缓存,存在Map里 protected final Map<String, Cache> caches = new HashMap<>(); // 结果映射,存在Map里 pro