原创 Mybatis经典9种设计模式【可收藏】

发布时间:2021-06-24 14:20:22 浏览 1376 来源:猿笔记 作者:Java小叮当

    Mybatis源码中使用了大量的设计模式,##6、模板方法模式,**接下来挨个模式进行解读,然后解读在Mybatis中怎样应用了该模式,Builder模式的定义是:就可以使用工厂模式和Builder模式,相对于工厂模式会产出一个完整的产品,Builder应用于更加复杂的对象的构建。然后做大量的XpathParser解析、配置或语法的解析、反射生成对象、存入结果缓存等步骤;因此大量采用了Builder模式来解决。在Mybatis中比如SqlSessionFactory使用的是工厂模式,简单工厂模式(SimpleFactoryPattern)。


    ##前言

    虽然我们都知道设计模式有26种,但大多停留在概念层面,在实际开发中很少遇到。Mybatis源代码中使用了大量的设计模式。阅读源代码,观察设计模式的应用,可以帮助我们更深入地理解设计模式。

    ##Mybatis至少遇到了以下设计模式

    ##1、Builder模式

    例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder。

    ##2,工厂模式

    例如SqlSessionFactory、ObjectFactory、MapperProxyFactory。

    ##3,单例模式

    例如ErrorContext和LogFactory。

    ##4,代理模式

    Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果。

    ##5,组合模式

    例如SqlNode和各个子类ChooseSqlNode等。

    ##6、模板方法模式

    例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler。

    ##7,适配器模式

    例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现。

    ##8.装饰模式

    例如Cache包中的cache.decorators子包中等各个装饰者的实现。

    ##9,迭代器模式

    例如迭代器模式PropertyTokenizer。

    * *接下来解释每个模式,首先介绍模式本身的知识,然后解释如何在Mybatis中应用模式。**

    ##一、Builder模式

    Builder模式的定义是“将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示。”一般来说,如果一个对象的构造比较复杂,超出了构造函数的范围,可以使用工厂模式和Builder模式。与工厂模式相比,它将生产出完整的产品。Builder适用于构建更复杂的对象,甚至只构建产品的一部分。

    在Mybatis环境的初始化过程中,SqlSessionFactoryBuilder会调用XMLConfigBuilder读取所有的MybatisMapConfig.xml和所有的Mapper.xml文件,构建Mybatis运行的核心对象Configuration对象,然后将该Configuration对象作为参数构建一个SqlSessionFactory对象。

    其中XMLConfigBuilder在构建Configuration对象时,也会调用XMLMapperBuilder用于读取*Mapper文件,而XMLMapperBuilder会使用XMLStatementBuilder来读取和build所有的SQL语句。

    在这个过程中,还有一个类似的特性,就是这些构建者会读取文件或者配置,然后做大量的XpathParser解析,配置或者语法解析,反射生成对象,存储在结果缓存中,等等。这么多工作不是一个构造函数能包含的,就用大量的构造函数来解决。

    **对于builder的具体类,方法都大都用build*开头,比如SqlSessionFactoryBuilder为例,它包含以下方法:**

    即根据不同的输入参数来构建SqlSessionFactory这个工厂对象。

    # #二。工厂模式

    比如在Mybatis中,SqlSessionFactory使用工厂模式,这是一种没有复杂逻辑的工厂方法模式。

    工厂方法模式(SimpleFactoryPattern),也称为StaticFactoryMethod模式,属于类创建模式。在工厂方法模式中,可以根据不同的参数返回不同类的实例。工厂方法模式专门定义一个类来创建其他类的实例,创建的实例通常有一个公共的父类。

    SqlSession可以认为是一个Mybatis工作的核心的接口,通过这个接口可以执行执行SQL语句、获取Mappers、管理事务。类似于连接MySQL的Connection对象。

    可以看到,该Factory的openSession方法重载了很多个,分别支持autoCommit、Executor、Transaction等参数的输入,来构建核心的SqlSession对象。

    **在DefaultSqlSessionFactory的默认工厂实现里,有一个方法可以看出工厂怎么产出一个产品:**

    \tprivateSqlSessionopenSessionFromDataSource(ExecutorTypeexecType,TransactionIsolationLevellevel,

    \t\t\tbooleanautoCommit){

    \t\tTransactiontx=null;

    \t\ttry{

    \t\t\tfinalEnvironmentenvironment=configuration.getEnvironment();

    \t\t\tfinalTransactionFactorytransactionFactory=getTransactionFactoryFromEnvironment(environment);

    \t\t\ttx=transactionFactory.newTransaction(environment.getDataSource(),level,autoCommit);

    \t\t\tfinalExecutorexecutor=configuration.newExecutor(tx,execType);

    \t\t\treturnnewDefaultSqlSession(configuration,executor,autoCommit);

    \t\t}catch(Exceptione){

    \t\t\tcloseTransaction(tx);//mayhavefetchedaconnectionsoletscall

    \t\t\t\t\t\t\t\t\t//close()

    \t\t\tthrowExceptionFactory.wrapException("Erroropeningsession.Cause:"+e,e);

    \t\t}finally{

    \t\t\tErrorContext.instance().reset();

    \t\t}

    \t}这是一个openSession调用的底层方法,该方法先从configuration读取对应的环境配置,然后初始化TransactionFactory获得一个Transaction对象,然后通过Transaction获取一个Executor对象,最后通过configuration、Executor、是否autoCommit三个参数构建了SqlSession。

    其实我们在这里也可以看到线索,SqlSession的执行实际上是委托给了对应的Executor。

    **而对于LogFactory,它的实现代码:**

    publicfinalclassLogFactory{

    \tprivatestaticConstructorlogConstructor;

    \tprivateLogFactory(){

    \t\t//disableconstruction

    \t}

    \tpublicstaticLoggetLog(Class<>aClass){

    \t\treturngetLog(aClass.getName());

    \t}这里有个特别的地方,是Log变量的的类型是Constructor,也就是说该工厂生产的不只是一个产品,而是具有Log公共接口的一系列产品,比如Log4jImpl、Slf4jImpl等很多具体的Log。

    # #三。单一模式

    singleton pattern:singleton pattern确保一个类只有一个实例,并实例化自己,将这个实例提供给整个系统。这个类叫做singleton类,它提供了一个全局访问方法。

    单例模式主要有三点:第一,一个类只能有一个实例;第二,它必须自己创建这个实例;第三,它必须自己给整个系统提供这个例子。单例模式是一种对象创建模式。单件模式也称为单件模式或单一状态模式。

    Mybatis中有两个地方使用单例模式,ErrorContext和LogFactory,其中ErrorContext是每个线程中使用的单个实例,用于记录线程执行环境的错误信息,而LogFactory是为整个Mybatis提供的日志工厂,用于获取为项目配置的日志对象。

    **ErrorContext的单例实现代码:**

    publicclassErrorContext{

    \tprivatestaticfinalThreadLocalLOCAL=newThreadLocal();

    \tprivateErrorContext(){

    \t}

    \tpublicstaticErrorContextinstance(){

    \t\tErrorContextcontext=LOCAL.get();

    \t\tif(context==null){

    \t\t\tcontext=newErrorContext();

    \t\t\tLOCAL.set(context);

    \t\t}

    \t\treturncontext;

    \t}构造函数由private修改,并具有静态本地实例变量和获取实例变量的方法。在获取实例的方法中,首先判断它是否为空,如果是,先创建它,然后返回构造的对象。

    这里只有一个有趣的点。本地的静态实例变量由线程本地修改,这意味着它属于每个线程自己的数据。在instance()方法中,首先获取该线程的实例,如果不是,则创建该线程唯一的ErrorContext。

    # #四。代理模式

    代理模式可以认为是Mybatis的核心模式。因为这种模式,我们只需要写Mapper.java接口,不

作者信息

Java小叮当 [等级:3] Java工程师
发布了 90 篇专栏 · 获得点赞 425 · 获得阅读 23613

相关推荐 更多