我们知道,Mybatis最终是通过SqlSession对象来执行sql语句的。通过前面的文章,我们也知道了Mybatis是如何解析mapper.xml文件,以及如何将sql语句读入Mybatis的Congifuration对象中,最后Mapper接口的代理对象是如何匹配SQL语句,最终执行SQL语句的通过SqlSession对象。上面的整个过程我们已经了解了,唯一没有分析的问题是:SqlSession是如何初始化的?而他是如何执行sql语句的呢?今天的主要目标就是搞清楚上面两个问题:SqlSession对象的创建或者初始化过程。SqlSession执行sql语句的具体过程。SqlSession对象是在不同的项目中创建的,SqlSession的创建过程会有不同,但基本是一样的。今天我们主要分析Springboot+Mybatis项目中SqlSession的创建过程。在Springboot项目中,Mybatis的初始化主要是通过配置类MybatisAutoConfiguration来完成的。MybatisAutoConfiguration主要完成:创建并初始化Configuration对象,通过SqlSessionFactoryBean初始化SqlSessionFactory(初始化为DefaultSqlSessionFactory)初始化SqlSession,Spring项目SqlSession初始化为SqlSessionTemplate对象,最后通过SqlSessionFactoryBean的build方法创建并返回DefaultSqlSessionFactory对象,交给SpringIoc容器管理。@Bean@ConditionalOnMissingBeanpublicSqlSessionFactorysqlSessionFactory(DataSourcedataSource)抛出异常{SqlSessionFactoryBeanfactory=newSqlSessionFactoryBean();factory.setDataSource(dataSource);))){factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));}applyConfiguration(factory);//省略returnfactory.getObject();MybatisAutoConfiguration#sqlSessionTemplatesqlSessionTemplate对象是Spring+Mybatis项目中的SqlSession登陆对象,可以通过sqlSessionTemplate实现Spring与Mybatis的无缝连接。通过上面SqlSession的类结构,我们知道SqlSessionTemplate其实是SqlSession的一个实现类。所以用@Bean注解的方法sqlSessionTemplate(SqlSessionFactorysqlSessionFactory)最终返回SqlSessionTemplate对象的目的是创建SqlSession对象,最后交给Spring的Ioc容器管理。其中参数SqlSessionFactory是通过SpringIoc依赖注册的DefaultSqlSessionFactory对比:@Bean@ConditionalOnMissingBeanpublicSqlSessionTemplatesqlSessionTemplate(SqlSessionFactorysqlSessionFactory){ExecutorTypeexecutorType.();ExecutorType=this.if(executorType!=null){returnnewSqlSessionTemplate(sqlSessionFactory,executorType);}else{返回新的SqlSessionTemplate(sqlSessionFactory);}}最终会调用到SqlSessionTemplate的SqlSessionTemplate方法:publicSqlSessionTemplate(SqlSessionFactorysqlSessionFactory,ExecutorTypeexecutorType,PersistenceExceptionTranslatorexceptionTranslator){notNull(sqlSessionFactory,"Property'sqlSessionFactory'isrequired");notNull(executorType,"属性'executorType'是必需的");this.sqlSessionFactory=sqlSessionFactory;this.executorType=executorType;this.exceptionTranslator=exceptionTranslator;this.sqlSessionProxy=(SqlSession)newProxyInstance(SqlSessionFactory.class.getClassLoader(),newClass[]{SqlSession.class},newSqlSessionInterceptor());}我们需要重点关注代码的最后一句,创建一个动态代理对象(也是动态代理)赋值给SqlSessionTelmplate对象的sqlSessionProxy。这个代理对象的回调对象是SqlSessionInterceptor。JDK动态代理大家已经很熟悉了。我们知道所有对代理对象sqlSessionProxy的方法调用最终都会调用回调对象SqlSessionInterceptor的invoke方法。现在,到这里我们知道Mybatis最重要的对象SqlSession已经创建好了。它实际上是SqlSessionTelmplate对象。我们还需要搞清楚它的两个重要属性:sqlSessionFactory:其实就是通过参数传入的DefaultSqlSessionFatcory对象。sqlSessionProxy:其实就是一个以SqlSessionInterceptor为回调对象的JDK动态代理对象。SqlSession执行SQL语句的具体过程其实在上一篇文章中已经分析过了。通过上一篇文章,我们已经知道了mapper.xml文件中的SQL语句是如何解析成Configuration对象的mappedStatements的,也了解了mapper接口中的方法是如何最终匹配Configuration对象中的mappedStatements并最终执行的里面有SQL语句。整个过程我们已经清楚了,但是最终的sql语句是通过sqlSession对象来执行的。上一篇没有详细分析sqlSession执行sql语句的具体过程。现在就来详细分析一下这部分。通过前面的分析,现在我们知道了sqlSession对象其实就是一个SqlSessionTelmplate对象,下面以selectOne方法为例,直接看SqlSessionTelmplate的selectOne方法。我们知道,如果mapper.xml文件中select语句的返回类型不是列表而是实体对象,比如selectXXXById通过主键值返回一条记录时,最终会匹配到selectOne方法。看一下SqlSessionTelmplate的源码,是交给sqlSessionProxy处理的。其实我们可以看到,SqlSessionTelmplate所有的SQL语句执行方法最终都委托给了sqlSessionProxy来处理。我们已经知道这个sqlSessionProxy其实是一个动态代理对象,它最终会调用回调对象SqlSessionInterceptor的invoke方法。@Overridepublic
