理清Mybatis的启动装配和调用原理

        我们写CURD的时候,一个常规的做法就是,通常会定义一个接口Mapper,然后再写一个XML文件定义SQL或者直接在Mapper方法上打赏CURD注解写sql语句,然后在业务中使用。

        那有没有想过,我们定义的类如何被装载到Bean中的,为何我们可以Autowired自动装配? 我们访问mapper的方法为什么会自动映射到XML中对应的语句上?本文就是要缕清这件事。

        先说些类的作用,或者叫做术语表。

        MybatisAutoConfiguration:Mybatis的自动装配类,会注册bean,加载Mybatis配置,扫描包路径;

        SqlSessionFactoryBean:用于创建SqlSessionFactory类Bean的bean,通过该类可以实现对包的扫描,将重要信息加载到JVM中,非常重要的一个类;

        SqlSessionFactory:SqlSession的工厂类,用于创建SqlSession。

        SqlSession:是mybatis提供CURD的API接口层;

        Configuration:mybatis的配置类,几乎所有重要信息都会加载到该类中,包括sql语句,Mapper接口等;

        MapperRegistry:会注册Mapper接口类;

        MapperFactoryBean:factoryBean,创建Mapper代理类的bean。

        MapperProxy是我们定义的接口类的代理类,用来进行实际sql操作;

        MapperScannerConfigurer:负责将业务自定义的mapper接口类注册到Ioc容器中,bean的实际类是MapperFactoryBean。

 我画了一个类图,整体上展示了mybatis的装配和调用原理:

启动时,MybatisAutoConfiguration会进行自动装配。

       1、加载SqlSessionTemplate到容器;

       2、加载SqlSesstionFactoryBean,该FactoryBean在初始化的时候会创建SqlSessionFactory,并会扫描包路径,进行sql语句加载、Mapper接口类的加载;

       3、创建SqlSessionFactory时需要根据扫描包路径进行加载。首先是会扫描所有的xml文件,并将所有的语句放入map中,key是namespace+id,value就是实际语句。namespace就是我们写的实际mapper。这个map是作为Mybatis的配置类Configuration的一个属性。也就是说上一步完成了所有sql语句的加载。这个map是mappedStatements。

      4、接着SqlSessionFactory还会扫描所有Mapper接口类,并将其放入另外一个map中,knownMapper中,key就是我们定义的接口类,value是MapperProxy,MapperProxy目的是获取实际的sql。

       好,现在可以看到上面有两个map存放了sql语句,一个存了接口类的map。实际上通过MapperProxy就可以找到mappedStatments中的sql。但问题是,我们在使用时,是使用Autowired,即我们的接口类是给装载到IOC容器中的bean,何时加载的?

      5、在启动时,MapperScannerConfigurer会负责进行bean的注入。其会调用ClassPathMapperSacanner扫描所有的Mapper接口,并将其注册到IoC容器中,对应的beanClass设置为MapperFactoryBean,也就是我们在注入的使用时,直接上是注册了MapperFactoryBean,我们在引用时,会调用该类的getObject,这个方法实际上是通过接口类到knownMapper找到了对应的mapperProxy。是的,我们注入获得的实际对象是MapperProxy。

       有了MapperProxy一切就顺理成章了。

      6、找到对应的sql后,还是会调用sqlSession对应的CURD方法,sqlSession的实现类是SqlSessionTemplate,其实际上会调用SqlSessionFactory去创建SqlSession,SqlSession负责具体的语句执行,当然他也不是自己做,还是交给下面的Executor去做。

       7、Executor作为Mybatis的核心执行器,负责全部sql的执行调度,它会调用下层的StatmentHandler,该类是对JDBC Statment的封装。看下源码:

 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);
    return stmt;
  }

//打开数据库连接
private void openConnection() throws SQLException {
        this.connection = DataSourceUtils.getConnection(this.dataSource);
        this.autoCommit = this.connection.getAutoCommit();

    }

connection会调用具体连接池Datasource创建或者复用。

下面是Mybatis的一个架构图(不是我画的),本文暂时不对Mybatis执行流程进行介绍,感兴趣可以看:Mybatis架构设计

        Mybatis本身只能算上是一个半ORM框架,因为我们还是需要自己写sql。这本身是不能接受的。因此国人在mybatis的基础上开发了一个全ORM框架,mybatis-plus。他依然采用mybatis的架构思想,只是在此基础上做了功能增加,如分页、主键id的自动生成。MybatisPlusAutoConfiguration负责创建SqlSessionFactory,其在里面增加了主键生成器、sql注入器等bean。其次通过使用自定义的MapperProxy。在执行sql的时候会调用器自定义的MybatisMapperMethod ,其会执行真正的sql。具体源码这里就不解析了,具体可看mybatis-plus的官网或者这篇文章:https://blog.csdn.net/m0_71777195/article/details/125521015。

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值