mybatis和spring的整合中用到了sqlsessionTemplate,该类实现了SqlSession接口,同时又有一个SqlSession属性,这个属性是一个SqlSession的代理,最后转而执行的是SqlSessionInterceptor这个类里的invoke方法,没错SqlSessionInterceptor实现了InvocationHandler接口。在执行器使用sqlsession时最终会到这个类里去执行。
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator)
{
Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
Assert.notNull(executorType, "Property 'executorType' is required");
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
this.sqlSessionProxy = ((SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor(null)));
}
private class SqlSessionInterceptor implements InvocationHandler
{
private SqlSessionInterceptor()
{
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
try
{
Object result = method.invoke(sqlSession, args);
if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory))
{
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
if ((SqlSessionTemplate.this.exceptionTranslator != null) && ((unwrapped instanceof PersistenceException))) {
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
在和spring的整合除了给可以给Dao层注入sqlsessionTemplate来管理sqlsession,省去创建sqlsession和关闭sqlsession的代码工作,也可以通过继承SqlSessionDaoSupport这个抽象类,SqlSessionDaoSupport类主要是对sqlsessionTemplate这个再一次封装而已。他有两个属性sqlSessionFactory和sqlSessionTemplate,由spring通过自动装配选择其一来完成,省去了为每个类注入的sqlsessionTemplate的麻烦。但也有缺点就是单继承的问题。
接下来spring还提供了通过mapper代理的配置,主要是MapperFactoryBean和MapperScannerConfigurer。
MapperFactoryBean这个类是用来生成所有mapper接口类的代理类的。他继承了SqlSessionDaoSupport抽象类,实现了FactoryBean接口。
实现了FactoryBean后,spring在获取该对象时候会调用getObject方法,最后调用sqlsession的getMapper方法,也就是实际获取的就是接口的代理类。也就是我们在业务层注入的mapper接口就是MapperFactoryBean生成的一个代理类。
public T getObject()
throws Exception
{
return getSqlSession().getMapper(this.mapperInterface);
}
由于一个mapper接口需要配置一个MapperFactoryBean,多了就比较麻烦从而产生了MapperScannerConfigurer