zoukankan      html  css  js  c++  java
  • Spring,tk-mapper源码阅读

    Mybatis的源码学习(一):

     前言:

         结合spring本次学习会先从spring-mybatis开始分析

      在学习mybatis之前,应该要对spring的bean有所了解,本文略过

      先贴一下mybatis的配置:

     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="mapperLocations">
                <array>
                    <value>classpath:mapper/**/*.xml</value>
                </array>
            </property>
            <property name="typeAliasesPackage" value="xxxx.model"/>
            <property name="plugins">
                <array>
                    <bean class="com.github.pagehelper.PageHelper">
                        <property name="properties">
                            <value>
                                dialect=mysql
                                reasonable=true
                            </value>
                        </property>
                    </bean>
                </array>
            </property>
        </bean>
     <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="xxxx.mapper"/>
     </bean>
    
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>

    先看第一个配置,配置 

    <property name="dataSource" ref="dataSource"/>

     这段即spring IOC 依赖注入的特性,将数据库的配置信息设置到该set方法中

            <property name="mapperLocations">
                <array>
                    <value>classpath:mapper/**/*.xml</value>
                </array>
            </property>

    该属性是扫描mapper的xml配置

     <property name="typeAliasesPackage" value="xxxx.model"/>

    这个配置即为model(或者entity/domain)类设置别名

    <property name="plugins">
                <array>
                    <bean class="com.github.pagehelper.PageHelper">
                        <property name="properties">
                            <value>
                                dialect=mysql
                                reasonable=true
                            </value>
                        </property>
                    </bean>
                </array>
     </property>

    这个配置是集成了分页的pahelper插件,

    配置看完了,现在就开始看java代码了

    配置好项目之后,找到SqlSessionFactoryBean然后启动tomcat,为什么要找这个类呢?因为这个类就是spring注入mabatis属性的一个入口(将mybatis和spring整合)

    结合上面配置内容

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

    底下的所有操作都是为Configuration设置塞值,为了不影响篇幅冗余,暂且略过这些

    说一下下面这句

    扫描注册Mapper接口

    在初始化的时候已经将mapper解析xml的时候已经将mapper注册为一个mapper bean 了
     完成上述操作之后,mapper下的所有接口都已经与xml的namespace匹配上,并且mapper注册为一个代理类

    最后一句代码就完成转化

    调试到 SqlSessionFactoryBuilder,发现默认创建了 DefaultSqlSessionFactory

    建立了sqlSessionFactory

    下来是扫描

    <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">

    看一下这个类的继承关系

    我们看到了这个类实现了BeanDefinitionRegistryPostProcessor接口,此接口即动态的将Bean的内容进行动态修改

    方法实现即在下方 

    执行完上面那个方法之后,tk-mapper开始往下执行,由于一开始spring在扫描sqlSessionFactoryBuilder的时候就已经把mapper命名空间什么的已经扫描过,所以这块不会再去注册mapperBean 

    下面的注册mapper接口在前面已经执行过了

     

    接下来注入sqlSession模板类,这个类是通过动态代理的方式获取执行器并执行sql

    看下配置

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>

    spring开始扫描这个配置,打开调试器,看一下SqlSessionTemplate的继承图

    它继承了SqlSession接口,还有一个SqlSession对象?这个是什么操作?

    看构造方法,原来作者这样的设计是让 sqlSessionProxy代理  对SqlSession进行操作

      public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
          PersistenceExceptionTranslator exceptionTranslator) {
    
        notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
        notNull(executorType, "Property 'executorType' is required");
    
        this.sqlSessionFactory = sqlSessionFactory;
        this.executorType = executorType;
        this.exceptionTranslator = exceptionTranslator;
    //代理对象创建执行器,并连接DB进行操作
    this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); }
     /**
       * Proxy needed to route MyBatis method calls to the proper SqlSession got
       * from Spring's Transaction Manager
       * It also unwraps exceptions thrown by {@code Method#invoke(Object, Object...)} to
       * pass a {@code PersistenceException} to the {@code PersistenceExceptionTranslator}.
       */
      private class SqlSessionInterceptor implements InvocationHandler {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       //这里的实际对象是DefaultSqlSession SqlSession sqlSession
    = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try {
         //执行目标方法(即调用Executor并组装成sql进行db操作) Object result
    = method.invoke(sqlSession, args); if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { // force commit even on non-dirty sessions because some databases require // a commit/rollback before calling close() sqlSession.commit(true); } return result; } catch (Throwable t) { Throwable unwrapped = unwrapThrowable(t); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { // release the connection to avoid a deadlock if the translator is no loaded. See issue #22 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); sqlSession = null; Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); if (translated != null) { unwrapped = translated; } } throw unwrapped; } finally { if (sqlSession != null) { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } }

    不得不说,作者的设计架构是真的很棒

    下一文 说一下mybatis的动态代理

  • 相关阅读:
    使用mongodb保存爬取豆瓣电影的数据
    使用scrapy爬取阳光热线问政平台
    使用scrapy爬取手机版斗鱼主播的房间图片及昵称
    使用selenium + chrome爬取中国大学Mooc网的计算机学科的所有课程链接
    使用scrapy爬取腾讯社招,获取所有分页的职位名称及chaolia、类型、人数、工作地点、发布日期超链接
    python2使用bs4爬取腾讯社招
    使用python2爬取百度贴吧指定关键字和分页帖子楼主所发的图片
    提问的智慧
    深刻理解系统架构师和系统分析师定义
    Redis基础数据结构与核心原理
  • 原文地址:https://www.cnblogs.com/ChoviWu/p/10118051.html
Copyright © 2011-2022 走看看