老套路,先上案例代码,我们就按照这个案例一步步搞定Mybatis源码。publicclassMybatisApplication{publicstaticfinalStringURL="jdbc:mysql://localhost:3306/mblog";publicstaticfinalStringUSER="root";publicstaticfinalStringPASSWORD="123456";publicstaticvoidmain(String[]args){Stringresource="mybatis-config.xml";InputStreaminputStream=null;SqlSessionsqlSession=null;try{inputStream=Resources.getResourceAsStream(resource);SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);sqlSession=sqlSessionFactory.openSession();UserMapperuserMapper=sqlSession.getMapper(UserSystemMapper.class)。.println(userMapper.selectById(1));}catch(Exceptione){e.printStackTrace();}finally{try{inputStream.close();}catch(IOExceptione){e.printStackTrace();}sqlSession.close();}}因为很多小伙伴都在催,说Mybatis源码系列好像什么时候完结,所以熬夜写这篇文章。继续打开~~SqlSessionsqlSession=sqlSessionFactory.openSession();上一篇已经分析过了,这里的sqlSessionFactory其实就是DefaultSqlSessionFactory。所以这里,我们先从DefaultSqlSessionFactory中的openSession方法说起。publicclassDefaultSqlSessionFactoryimplementsSqlSessionFactory{privatefinalConfigurationconfiguration;publicDefaultSqlSessionFactory(Configurationconfiguration){this.configuration=configuration;}//创建session,这个方法直接调用本类中的另外一个方法@OverridepublicSqlSessionopenSession(){returnopenSessionFromDataSource(configuration.getDefaultExecutorType(),null,false);}//其实这个方法调用的是privateSqlSessionopenSessionFromDataSource(ExecutorTypeexecType,TransactionIsolationLevellevel,booleanautoCommit){Transactiontx=null;try{//对应xml标签,在解析配置文件的时候已经保存在configuration中了。finalEnvironmentenvironment=configuration.getEnvironment();finalTransactionFactorytransactionFactory=getTransactionFactoryFromEnvironment(environment);tx=transactionFactory.newTransaction(environment.getDataSource(),level,autoCommit);//创建执行器执行SQLfinalExecutorexecutor=configuration.x,newExecutor(Type)//这也解释了为什么我们代码中的SqlSession是DefaultSqlSessionreturnnewDefaultSqlSession(configuration,executor,autoCommit);}catch(Exceptione){closeTransaction(tx);//可能有fetchedaconnectionsoletscallclose()throwExceptionFactory.wrapException("Erroropeningausesession:"+Closing.e,e);}最后{ErrorContext.instance().reset();}}privateTransactionFactorygetTransactionFactoryFromEnvironment(Environmentenvironment){if(environment==null||environment.getTransactionFactory()==null){returnnewManagedTransactionFactory();}returnenvironment。getTransactionFactory();}这个方法的主要内容是:下面我们来一一分解。创建事务Transaction事务工厂类型可以配置为JDBC类型或MANAGED类型。JdbcTransactionFactory产生JdbcTransaction。ManagedTransactionFactory产生ManagedTransaction。如果配置了JDBC,将使用Connection对象的commit()、rollback()和close()方法来管理事务。如果我们配置MANAGED,事务将由容器来管理,比如JBOSS、Weblogic。因为我们是在本地运行的程序,如果配置成MANAGED,就没有事务了。但是如果Spring在我们的项目中集成了Mybatis,就不需要配置事务了,因为我们会直接在applicationContext.xml中配置数据源和事务管理器,从而覆盖Mybatis的配置。创建一个Executor,调用配置的newExecutor方法创建一个Executor。finalExecutorExecutor=configuration.newExecutor(tx,execType);//配置中的publicExecutornewExecutor(Transactiontransaction,ExecutorTypeexecutorType){executorType=executorType==null?defaultExecutorType:executorType;executorType=executorType==null?ExecutorType.SIMPLE:executorType;Executor/执行器第一步if(ExecutorType.BATCH==executorType){executor=newBatchExecutor(this,transaction);}elseif(ExecutorType.REUSE==executorType){executor=newReuseExecutor(this,transaction);}else{executor=newSimpleExecutor(this,transaction);}//第二步if(cacheEnabled){executor=newCachingExecutor(executor);}//第三步executor=(Executor)interceptorChain.pluginAll(executor);returnexecutor;}这个方法分为三步。第一步:创建执行器Executor分为三种基本类型:publicenumExecutorType{SIMPLE,REUSE,BATCH}SIMPLE是默认类型。为什么要让抽象类BaseExecutor实现Executor接口,然后让具体实现类继承抽象类呢?这就是模板方法模式的实现。模板方法模式就是定义一个算法骨架,让子类为一个或多个步骤提供实现。模板方法允许子类在不改变算法结构的情况下重新定义算法的某些步骤。抽象方法在子类中实现。每个executor实现自己的逻辑,BaseExecutor最终会被调用到具体的子类中。抽象方法protectedabstractintdoUpdate(MappedStatementms,Objectparameter)throwsSQLException;protectedabstractListdoFlushStatements(booleanisRollback)throwsSQLException;protectedabstractListdoQuery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql)throwsSQLException;protectedabstractCursordoQueryCursor(MappedStatementms,Objectparameter,RowBoundsrowBounds,BoundSqlboundSql)throwsSQLException;第二步:缓存装饰上面代码中的第二步if(cacheEnabled){executor=newCachingExecutor(executor);}如果cacheEnabled=true,会使用装饰器设计模式装饰Executor。第三步:插件代理缓存装饰完成后,会执行executor=(Executor)interceptorChain.pluginAll(executor);这里会在Executor中植入插件逻辑。例如:在分页插件中,需要在插件中植入Executor。至此,执行器的创建就完成了。创建一个DefaultSqlSession对象,将解析配置文件创建的Configuration对象和创建的Executor赋值给DefaultSqlSession中的属性。publicDefaultSqlSession(Configurationconfiguration,Executorexecutor,booleanautoCommit){this.configuration=configuration;this.executor=executor;this.dirty=false;this.autoCommit=autoCommit;}这里创建了SqlSession(DefaultSqlSession)对象。总结一下这篇文章,我们讲了几个创建SqlSession的步骤,最后我们得到了一个DefaultSqlSession对象,里面包含了执行器Executor和配置对象Configuration。Executor是SQL的实际执行对象。Configuration保存配置文件内容。本文源码分析全过程如下:本文转载自微信公众号《Java后端技术全栈》,可通过以下二维码关注。转载本文请联系Java后端技术全栈公众号。