第六篇 mybatis的运行原理(3):工厂方法模式,SqlSession的创建

一、工厂方法模式

            工厂模式是java中最常用的创建型设计模式之一,和之前提到的builder模式一样,主要目的是为了代替new关键字创建对象的方式。工厂模式主要分三种,

       简单工厂模式,工厂方法模式,抽象工厂模式。

      (1) 简单工厂模式就是通过创建一个可以创建所有目标接口子类的工厂类,然后根据不同的需求,创建不同的目标类,虽然达到了工厂模式的目的,

               但是工厂类内部耦合严重,当需要增加新的目标子类创建方式时,就得去修改工厂类,扩展性差。

       (2)工厂方法模式是在简单工厂模式的基础上进行了进一步解耦,通过封装,让使用对象的不去关心对象的具体创建,只关注该类的功能,让代码

                更加整洁

       (3)抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一

               个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法

               模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类,抽象工厂模式才是实际意义

               的工厂模式。

    由于接下来的内容只用了工厂方法模式,所以这里只举该模式的例子。

package com.fan.seckill.factory;

/**
 * 生产工厂接口
 */
public interface ProducerFactory {
    public Food createFood(String foodType);
}
package com.fan.seckill.factory;

/**
 * 产品食物接口
 */
public interface Food {
    void getFoodType();
}
package com.fan.seckill.factory;

/**
 * 生产工厂默认实现类
 */
public class DefaultProducerFactory implements ProducerFactory{

    private Food food;
    @Override
    public Food createFood(String foodType) {
        if("rice".equals(foodType)) {
            food = new RiceFood();
        } else {
            food = new NoodleFood();
        }
        return this.food;
    }
}
package com.fan.seckill.factory;

/**
 * 食物默认实现类(面条)
 */
public class NoodleFood implements Food{
    @Override
    public void getFoodType() {
        System.out.println("面条!");
    }
}
package com.fan.seckill.factory;

/**
 * 食物默认实现类(米饭)
 */
public class RiceFood implements Food{
    @Override
    public void getFoodType() {
        System.out.println("米饭!");
    }
}
package com.fan.seckill.factory;

public class Test {
    public static void main(String[] args) {
        ProducerFactory producerFactory = new DefaultProducerFactory();
        Food food = producerFactory.createFood("noodle");
        food.getFoodType();
    }
}

从上面main方法的创建中就可以看出,食物的创建并没有涉及到具体实现类的操作,都是由接口完成,封装了具体的实现,只关注改接口的功能。

 

二、SqlSession的创建

     SqlSession接口是mybatis的核心接口之一,mybatis提供了两个实现类,SqlSessionManager类和DefaultSqlSession类,创建过程中使用了工厂方法模式,开发人员常用

的DefaultSqlSession类,DefaultSqlSession对象的创建依赖于DefaultSqlSessionFactory类,下面是他们之间的关系依赖图。

DefaultSqlSessionFactory类是一个具体工厂类,根据参数的不同需求,提供了多种创建sqlsession对象的方式,

最终归为两种创建方式,一种是根据数据源获取数据库连接创建sqlSession。另一种是通过已有的数据库连接对象创建sqlSession。

SqlSessionFactory 接口提供的所有重载方式:

public interface SqlSessionFactory {
    SqlSession openSession();

    SqlSession openSession(boolean var1);

    SqlSession openSession(Connection var1);

    SqlSession openSession(TransactionIsolationLevel var1);

    SqlSession openSession(ExecutorType var1);

    SqlSession openSession(ExecutorType var1, boolean var2);

    SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);

    SqlSession openSession(ExecutorType var1, Connection var2);

    Configuration getConfiguration();
}

第一种创建方式:

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;

        DefaultSqlSession var8;
        try {
            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var12) {
            this.closeTransaction(tx);
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);
        } finally {
            ErrorContext.instance().reset();
        }

        return var8;
    }

第二种创建方式:

private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
        DefaultSqlSession var8;
        try {
            boolean autoCommit;
            try {
                autoCommit = connection.getAutoCommit();
            } catch (SQLException var13) {
                autoCommit = true;
            }

            Environment environment = this.configuration.getEnvironment();
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            Transaction tx = transactionFactory.newTransaction(connection);
            Executor executor = this.configuration.newExecutor(tx, execType);
            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var14, var14);
        } finally {
            ErrorContext.instance().reset();
        }

        return var8;
    }

     为什么会有这两种创建方式,主要还是因为构建connection的原因,我们知道ORM框架底层还是由JDBC实现,所以连接数据库离不开connection对象,正常我们使用mybatis时都会

配置数据库连接池这时候,connection的创建不再由mybatis维护,所以mybatis创建数据库会话只需要使用现成的connection即可,所以在正常开发中,我们还是常用第二种方式。

      具体的创建一个sqlsession会话对象,除了之前学习过的配置对象configuration,还需要执行器对象executor,以及事务的默认提交属性 autoCommit创建方法主要完成以下几件事:

(1)获取事务配置环境environment ,创建TransactionFactory对象(具体的该对象的获取会在下篇博文提到)

(2)构建一个事务对象tx

(3)根据执行器类型构建执行器对象executor

(4)使用SqlSession的默认实现类DefaultSqlSession创建sqlsession对象

posted @ 2019-08-15 19:24  哲雪君!  阅读(1441)  评论(0编辑  收藏  举报