第四篇 mybatis的运行原理:重要组件的介绍
Posted zhexuejun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第四篇 mybatis的运行原理:重要组件的介绍相关的知识,希望对你有一定的参考价值。
一、组件介绍
相比其他框架,mybatis的组件构成还是相对简单的,下面是网络上比较常见的一张图,关于mybatis的执行流程,其中是mybatis的最常用的组件:
在来学习mybatis的源码和底层原理之前,先来了解各大组件的作用和生命周期:
(1)SqlSessionFactoryBuilder
SqlSessionFactoryBuilder是利用XML或者Java编码获得资源来构建SqlSessionFactory的,通过它可以构建多个SqlsessionFactory,它的作用就是一个构建器,一旦创建SqlSessionFactory,
它的作用就会消失,所以构建SqlsessionFactory成功后会废弃回收。所以的它的生命周期只存在于方法的局部,它的作用就是生成SqlSessionFactory对象。
(2)SqlSessionFactory对象
SqlSessionFactory的作用就是创建SqlSession,Sqlsession相当于JDBC中的Connection对象,每次访问数据库都需要创建SqlSession,前面的文章就已经说过,一个SqlSessionFactory对应一个数据库,
那么能不能多个对应一个数据库了?是可以的,但是这样做的话,有多个SqlSessionFactory就会有很多的数据库连接,这样会导致数据库连接资源容易耗尽,且不易管理数据库连接,所以,mybatis的设计采用的单例
模式,这样可以更有效的管理数据库的资源分配。由于SqlSessionFactory一直维护着SqlSession的创建,所以SqlSessionFactory的生命周期是框架运行的整个过程。
(3)SqlSession
SqlSession对象时连接数据库的通道,更准确地说是访问数据库的一次会话,当发起访问数据库的请求时,创建一个SqlSession对象,请求完成关闭SqlSession。 要注意的是,SqlSession是一个线程不安全的对象,
在涉及多线程的时候,要保证操作数据库的隔离级别 、数据库锁等高级特性,此外,SqlSession使用完成后都必须及时的关闭,避免占用连接资源,导致数据库宕机
(4)Mapper
Mapper是一个接口,它的作用是发送SQL,当然,作为接口,当然不能执行SQL, 所以Mapper是代理方式完成这一操作, 然后返回我们需要的结果,或者执行SQL从而修改数据库的数据,具体实现,后面会说。
因此,Mapper是一个方法级别的东西,当SqlSession销毁时,Mapper也会随之销毁。
二、SqlSessionFactory的创建
前面已经知道了mybatis的使用,执行流程以及重要的组件构成,但是对于一名开发者来说,知道这些远远不够,学习mybatis的底层原理,可以帮我们更好解决框架使用中的问题,甚至可以修改框架或者自定义插件来满足我们的业务需求。
所以我们从源码层面一步一步走mybatis的执行流程。 首先,从mybatis加载解析mybatis的配置文件mybatisConfig.xml开始。我们先来看看我们是如何创建SqlSessionFactory的:
/*资源*/ InputStream is = UserService.class.getClassLoader().getResourceAsStream("mybatis/mybatisConfig.xml") /*创建SqlSessionFactory*/ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
由上述代码可以看出SqlSessionFactory的创建是依托于SqlSessionFactoryBuilder类的build方法,打开该类SqlSessionFactoryBuilder由众多形式的build方法组成,尽管方法有很多,但是目的只有一个那就是
解析资源,创建SqlSessionFactory,所以我们以public SqlSessionFactory build(InputStream inputStream)为例深入
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) try /*解析xml文件,封装成一个XMLConfigBuilder对象*/ XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); /*生成一个参数类Configuration对象,然后通过该参数类创建DefaultSqlSessionFactory对象*/ Configuration config = parser.parse(); return build(config); catch (Exception e) throw ExceptionFactory.wrapException("Error building SqlSession.", e); finally ErrorContext.instance().reset(); try inputStream.close(); catch (IOException e) // Intentionally ignore. Prefer previous error. public SqlSessionFactory build(Configuration config) return new DefaultSqlSessionFactory(config);
java对于xml文件资源的解析有dom解析,sax解析,dom4j解析,mybatis使用的dom方式,具体xml会在别的文章中说到,xml解析会得到一个 XMLConfigBuilder对象,
之后,XMLConfigBuilder对象会通过parse方法初始为一个Configuration对象,看看Configuration对象的内部,
public class Configuration protected Environment environment; protected boolean safeRowBoundsEnabled = false; protected boolean safeResultHandlerEnabled = true; protected boolean mapUnderscoreToCamelCase = false; protected boolean aggressiveLazyLoading = true; protected boolean multipleResultSetsEnabled = true; protected boolean useGeneratedKeys = false; protected boolean useColumnLabel = true; protected boolean cacheEnabled = true; protected boolean callSettersOnNulls = false; protected String logPrefix; protected Class <? extends Log> logImpl; protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION; protected JdbcType jdbcTypeForNull = JdbcType.OTHER; protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] "equals", "clone", "hashCode", "toString" )); protected Integer defaultStatementTimeout; protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE; protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL; ..... .....
从熟悉的变量名就可以联想到这个对象就是xml文件里对mybatis配置属性,那为什么这些属性不直接放到DefaultSqlSessionFactory类里面去了,这主要是由于创建SqlSessionFactory
需要的参数复杂,如果直接放到类的构造方法里面,这会导致大量的逻辑存在于类的构造方法中,所以使用一个参数类总领全局,分步构建,可以有效降低这种逻辑混乱的问题。
所以Configuration 对象也SqlSessionFactory创建过程中最重要的一个类。甚至mybatis的大多数的配置都是源于Configuration ,
Configuration 对象的作用:
1. 读取配置文件,包括初始化xml和映射器xml
2. 初始化基础配置,如果xml文件里set和typehandle
3. 提供单例,生成单例,为之后生成session提供配置
4. 执行一些重要的对象方法,如构建构造器executor等。
SqlSessionFactory接口有两个实现类:DefaultSqlSessionFactory类和SqlSessionManager类,但是是使用DefaultSqlSessionFactory创建SqlSessionFactory对象,下一篇将会剖析DefaultSqlSessionFactory具体的创建过程
以上是关于第四篇 mybatis的运行原理:重要组件的介绍的主要内容,如果未能解决你的问题,请参考以下文章
第四篇(续):熔断监控Hystrix Dashboard和熔断聚合监控Hystrix Turbine