<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:com/mybatis/mapping/*.xml" />
</bean>
我们知道这个类SqlSessionFactoryBean明显就是一个spring的类。我们也知道mybatis是持久化数据的框架。那么spring如果要整合mybatis他要做什么呢?
这件事情我们不妨去猜一猜:
第一猜:spring都是通过自己的容器管管理类的,那么mybatis要想整合,最终要包装成spring能够操控的factorybean。从名字SqlSessionFactoryBean有没有感?(吼吼)
第二猜:如果我们自己使用mybatis,其实就是调用底层他的接口去实现功能,那么spring把这件事情自己封装了,让我们调用他的 方法,他再去调用mybatis的方法,这样是不是就实现了mybatis和spring的整合?(呲牙)
在深入SqlSessionFactoryBean类具体源码之前,我们来看看mybatis的配置通常是什么样子的。
mybatis的内容包括哪些重要的部分,如果不清楚这些那么我们也无法知道spring是如何包装mybatis的。那么在没有spring之前,mybatis是如何自行工作的呢?
mybatis主要包括以下这七项配置项。如想深入配置具体内容请查看参考文献
properties:用于配置属性信息。 settings:用于配置MyBatis的运行时方式。 typeAliases:配置类型别名,可以在xml中用别名取代全限定名。 typeHandlers:配置类型处理器。 plugins:配置拦截器,用于拦截sql语句的执行。 environments:配置数据源信息、连接池、事务属性等。 mappers:配置SQL映射文件。没有spring之前,使用mybatis需要以下几步骤。
1、jdk、tomcat(或者其他web容器),必需的。
2、创建一个web项目
3、解压mybatis3.2.3.zip文件,把mybatis-3.2.3.jar和lib目录下的所有jar包复制到WEB-INF/lib
4、复制mysql-connector-java-5.1.14.jar到WEB-INF/lib
5、在mysql创建一个mybatis数据库,新建一个user表,里面有id,name,password。
6、新建一个实体。
7、创建一个mapper接口
8、创建一个mapper.xml,里面写和mapper接口中定义一致的sql语句。
9、在classpath下创建mybatis配置文件mybatis-confi.xml,里面配置
<setting>
<typeAliases>
<environments>
<mappers>
10、新建一个能够生成mybatis工厂的单例类
public class MybatisUtil {
private static SqlSessionFactory sqlMapper; private static Reader reader; static { try { reader = Resources.getResourceAsReader("mybatis-config.xml"); sqlMapper = new SqlSessionFactoryBuilder().build(reader); } catch (Exception e) { e.printStackTrace(); } } public static SqlSessionFactory getInstance() { return sqlMapper; } }
最后,使用方式就是
创建工厂类-》打开session-》执行mapper接口中的语句(insert、update、select、delete)-》关闭session
spring要想集成mybatis,其实它就是把它拉来当“手下”,spring不去再关心数据持久化的具体过程(那都是mybatis要做的),他只要做的就是讲mybatis拉到自己的“办公室”来,给他“一把椅子”,让他乖乖工作。(然后偷笑!)
spring要想做到这一点其实不是容易的事情,因为spring的办公室很复杂,mybatis穿过办公室的门进入办公室就要大费周章。那么spring是怎么做到的呢?下面我们一起琢磨
SqlSessionFactoryBean类实现了接口FactoryBean<SqlSessionFactory>, InitializingBean。最终spring在调用getBean的时候返回的并不是类SqlSessionFactoryBean,而是他的属性类SqlSessionFactory的实例,代码如下:
public void afterPropertiesSet() throws Exception { notNull(dataSource, "Property 'dataSource' is required"); notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required"); this.sqlSessionFactory = buildSqlSessionFactory(); }public SqlSessionFactory getObject() throws Exception { if (this.sqlSessionFactory == null) { afterPropertiesSet(); } return this.sqlSessionFactory; }
至此,我们看到了sqlSessionFactory的实例生成,那么它有是如何注入到容器中的呢?
有了sqlSessionFactory 就要把它放置到容器中去管理。那么spring的容器如何载入这个类实例的哪?这里说的sqlSessionFactory是配置文件中SqlSessionFactoryBean对应的id。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:com/mybatis/mapping/*.xml" /></bean>
第一步:查看到web,来看看spring容器启动的入口类:org.springframework.web.context.ContextLoaderListener
这个类直接调用了方法contextInitialized初始化WebApplicationContext
最终xml中配置的mybatis类都成为了BeanDefinition放入到了spring容器中去管理。那么最终我们去执行sql语句的时候spring是执行的呢?
在我们调用到sql语句的时候,会把相应的mybatis代理类封装到HandlerMethod类中
设置到拦截器链条中(如图)
//类:AbstractHandlerMapping public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } return getHandlerExecutionChain(handler, request); }
然后spring的代理工厂会根据这个拦截器链条去调用mybatis的代理类去执行sql语句。
//MapperProxy<T> final MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); }
下面的章节我会详细分析各个部分。
参考文献:
http://my.oschina.net/u/1269959/blog/521703
http://blog.csdn.net/etttttss/article/details/8902125
http://mybatis.github.io/mybatis-3/zh/configuration.html
http://www.luoshengsha.com/266.html