mybatis源码解析
Posted 骆宏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis源码解析相关的知识,希望对你有一定的参考价值。
mybatis
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。想要更好的了解,大家可以查阅下官网的介绍。
核心类图
在这里面,我们一般会给出类图,但是要想制作一个类图,对于一个初步阅读源码的同学而言,还是有些难度的,因为难以抓住mybatis的要点,代码量也不小。下面我们换一个方式,使用idea的debug来观察数据。下面我们看一个spring集成mybatis的xml
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="$jdbc.app.driver"/>
<property name="url" value="$jdbc.app.url"/>
<property name="username" value="$jdbc.app.username"/>
<property name="password" value="$jdbc.app.password"/>
<property name="initialSize" value="$jdbc.app.initialSize"/>
<property name="maxActive" value="$jdbc.app.maxActive"/>
<property name="minIdle" value="$jdbc.app.minIdle"/>
<property name="maxWait" value="$jdbc.app.maxWait"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:com/ucweb/union/dao/app/*.xml"/>
<property name="plugins">
<list>
<ref bean="sqlInterceptor"/>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
在上面的xml中,我们发现,SqlSessiontionFactoryBean是集成spring的入口类,理所当然的,我们会先去观察下该类的接口,我们只观察该类的属性,以及方法签名即可。
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent>
private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);
private Resource configLocation;
private Configuration configuration;
private Resource[] mapperLocations;
private DataSource dataSource;
private TransactionFactory transactionFactory;
private Properties configurationProperties;
private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
private SqlSessionFactory sqlSessionFactory;
//EnvironmentAware requires spring 3.1
private String environment = SqlSessionFactoryBean.class.getSimpleName();
private boolean failFast;
private Interceptor[] plugins;
private TypeHandler<?>[] typeHandlers;
private String typeHandlersPackage;
private Class<?>[] typeAliases;
private String typeAliasesPackage;
private Class<?> typeAliasesSuperType;
//issue #19. No default provider.
private DatabaseIdProvider databaseIdProvider;
private Class<? extends VFS> vfs;
private Cache cache;
private ObjectFactory objectFactory;
private ObjectWrapperFactory objectWrapperFactory;
public void setObjectFactory(ObjectFactory objectFactory)
public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory)
public DatabaseIdProvider getDatabaseIdProvider()
public void setDatabaseIdProvider(DatabaseIdProvider databaseIdProvider)
public Class<? extends VFS> getVfs()
public void setVfs(Class<? extends VFS> vfs)
public Cache getCache()
public void setCache(Cache cache)
public void setPlugins(Interceptor[] plugins)
public void setTypeAliasesPackage(String typeAliasesPackage)
public void setTypeAliasesSuperType(Class<?> typeAliasesSuperType)
public void setTypeHandlersPackage(String typeHandlersPackage)
public void setTypeHandlers(TypeHandler<?>[] typeHandlers)
public void setTypeAliases(Class<?>[] typeAliases)
public void setFailFast(boolean failFast)
public void setConfigLocation(Resource configLocation)
public void setConfiguration(Configuration configuration)
public void setMapperLocations(Resource[] mapperLocations)
public void setConfigurationProperties(Properties sqlSessionFactoryProperties)
public void setDataSource(DataSource dataSource)
public void setSqlSessionFactoryBuilder(SqlSessionFactoryBuilder sqlSessionFactoryBuilder)
public void setTransactionFactory(TransactionFactory transactionFactory)
public void setEnvironment(String environment)
public void afterPropertiesSet() throws Exception
public SqlSessionFactory getObject() throws Exception;
public Class<? extends SqlSessionFactory> getObjectType();
public boolean isSingleton();
public void onApplicationEvent(ApplicationEvent event);
从这里面,我们粗略的看了下,可以发现该类其实做的工作就是在根据参数,来进行mybatis的配置,包括:mapper,mapper.xml,事务管理等。然后沿着这几个特性,我们一一展开,即可逐步探究mybatis的内部机制了。该篇文章只是抛砖引玉,从Configuration出发,来看看mybatis的内部秘密。为了缩短篇幅,我们直接启动程序,使用debug模式,找到任何一个mabatis执行的地方,打个断点,观察下Configuration类。如下图所示
篇幅有限,就不一一截图了,从图中的属性我们可以看到,Configuration类包含了非常多的信息,比如:Mapper,MappedStatement,Interceptor,ResultMap,SqlFragment。这些概念其实就是我们对应平时使用Mybatis最常接触到的部分,下面根据对应关系,简单的过一下
- Mapper,对应平时的Mapper类
- MappedStatement,就是mapper.xml中的<select>,<update>,<insert>,<delete>
- Interceptor,也就是myabtis的拦截器,比如常用的分页拦截器
- ResultMap,也就是mapper.xml中的<resultMap>
- SqlFragment,也就是mapper.xml中的dynamic sql部分,比如<if>,<where>,<foreach>等
从上面的列表可以看出,mybatis的封装很容易理解,有了上面的几个核心概念,接下来就是如何将mybatis的流程串起来,形成完整的调用过程了。由于这个模块,网上已经有很多作者写了不错的博客了,这里面我就不再细说,给个链接,有兴趣的朋友可以去查阅下,mybatis源码解析。
总结
阅读源码,需要非常良好的耐心以及找到核心要点。比如在阅读mybatis源码时,如果没有把握好方式,我们很可能陷入了一行一行的细节代码,而不得要义,大蛇还得打七寸,虽然使用了mybatis有一段时间了,经过这次的系统化学习,也算是对mybatis有了更加熟练的掌握。
延伸与扩展
- mybatis代码生成器的应用
- mybatis自定义拦截器的应用
- mybatis缓存的应用
以上是关于mybatis源码解析的主要内容,如果未能解决你的问题,请参考以下文章