Spring中Template模式与callback的结合使用浅析
Spring不论是与ibatis,还是与Hibernate的结合中,都使用到了Template模式与callback技术,来达到简化代码实现的目的。Template模式也即模板模式,用于对一些不太变化的流程进行模板化,与callback结合,可以将变化的部分出离出来,使用callback实现。然后根据不同的情况,向template注入不同的callback。那些模板代码就没有必要重复写了。我们看下spring和ibatis的结合中,Template和callback的使用:
public class SqlMapClientTemplate extends JdbcAccessor implements SqlMapClientOperations {
// ... ...
/**
* Execute the given data access action on a SqlMapExecutor.
* @param action callback object that specifies the data access action
* @return a result object returned by the action, or <code>null</code>
* @throws DataAccessException in case of SQL Maps errors
*/
public <T> T execute(SqlMapClientCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Assert.notNull(this.sqlMapClient, "No SqlMapClient specified"); // We always need to use a SqlMapSession, as we need to pass a Spring-managed
// Connection (potentially transactional) in. This shouldn't be necessary if
// we run against a TransactionAwareDataSourceProxy underneath, but unfortunately
// we still need it to make iBATIS batch execution work properly: If iBATIS
// doesn't recognize an existing transaction, it automatically executes the
// batch for every single statement... SqlMapSession session = this.sqlMapClient.openSession();
if (logger.isDebugEnabled()) {
logger.debug("Opened SqlMapSession [" + session + "] for iBATIS operation");
}
Connection ibatisCon = null; try {
Connection springCon = null;
DataSource dataSource = getDataSource();
boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy); // Obtain JDBC Connection to operate on...
try {
ibatisCon = session.getCurrentConnection();
if (ibatisCon == null) {
springCon = (transactionAware ?
dataSource.getConnection() : DataSourceUtils.doGetConnection(dataSource));
session.setUserConnection(springCon);
if (logger.isDebugEnabled()) {
logger.debug("Obtained JDBC Connection [" + springCon + "] for iBATIS operation");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Reusing JDBC Connection [" + ibatisCon + "] for iBATIS operation");
}
}
}
catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
} // Execute given callback...
try {
return action.doInSqlMapClient(session);
}
catch (SQLException ex) {
throw getExceptionTranslator().translate("SqlMapClient operation", null, ex);
}
finally {
try {
if (springCon != null) {
if (transactionAware) {
springCon.close();
}
else {
DataSourceUtils.doReleaseConnection(springCon, dataSource);
}
}
}
catch (Throwable ex) {
logger.debug("Could not close JDBC Connection", ex);
}
} // Processing finished - potentially session still to be closed.
}
finally {
// Only close SqlMapSession if we know we've actually opened it
// at the present level.
if (ibatisCon == null) {
session.close();
}
}
}
public <T> T execute(SqlMapClientCallback<T> action) throws DataAccessException
该方法就是一个模板方法,方法的参数是一个回调对象。在模板方法中,将一些相同的处理过程模板化,比如获得数据库连接,处理事务,处理异常,关闭资源等等,
这些都是每一个sql执行时都要面临的相同的过程,所以我们将他们房子模板方法中。然后将不同的部分通过 callback 对象作为参数传入进去,这样将模板代码和非
模板代码进行了隔离。没有必要将模板代码每次都写一遍。
public Object queryForObject(final String statementName, final Object parameterObject)
throws DataAccessException { return execute(new SqlMapClientCallback<Object>() {
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
return executor.queryForObject(statementName, parameterObject);
}
});
} public List queryForList(final String statementName, final Object parameterObject)
throws DataAccessException { return execute(new SqlMapClientCallback<List>() {
public List doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
return executor.queryForList(statementName, parameterObject);
}
});
} public Map queryForMap(
final String statementName, final Object parameterObject, final String keyProperty)
throws DataAccessException { return execute(new SqlMapClientCallback<Map>() {
public Map doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
return executor.queryForMap(statementName, parameterObject, keyProperty);
}
});
}
我们看一下上面这些方法,都是借助模板方法来处理那些每次都相同的流程,然后传入一个自己实现的 callback 对象。模板会自动回调我们在 callback 对象中定义的方法。
我们看下JdbcTemplate中的模板方法也是相似的:
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null"); Connection con = DataSourceUtils.getConnection(getDataSource());
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null) {
// Extract native JDBC Connection, castable to OracleConnection or the like.
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
else {
// Create close-suppressing Connection proxy, also preparing returned Statements.
conToUse = createConnectionProxy(con);
}
return action.doInConnection(conToUse);
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
}
finally {
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
Spring中Template模式与callback的结合使用浅析的更多相关文章
- (转)Spring中Singleton模式的线程安全
不知道哪里的文章,总结性还是比较好的.但是代码凌乱,有的还没有图.如果找到原文了可以进行替换! spring中的单例 spring中管理的bean实例默认情况下是单例的[sigleton类型],就还有 ...
- Spring中常用的23中设计模式
1.spring 中常用的设计模式有23中 分类 设计模式 创建型 工厂方法模式(FactoryMethod).抽象工厂模式(AbstractFactory).建造者模式(Builder).原型 ...
- Spring中使用的设计模式
目录 Spring使用的设计模式 1.单例模式 2.原型模式 3.模板模式 4.观察者模式 5.工厂模式 简单工厂模式 工厂方法模式 6.适配器模式 7.装饰者模式 8.代理模式 9.策略模式 S ...
- [转] 9种设计模式在Spring中的运用
作者:iCoding91地址:https://blog.csdn.net/caoxiaohong1005 转发的公众号地址,有其他设计模式介绍:https://mp.weixin.qq.com/s/Z ...
- 9种设计模式在Spring中的运用,一定要非常熟练
1.简单工厂(非23种设计模式中的一种) 实现方式: BeanFactory.Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数 ...
- Spring中的设计模式学习
Spring提供了一种Template的设计哲学,包含了很多优秀的软件工程思想. 1. 简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. ...
- Spring中的设计模式
[Spring中的设计模式] http://www.uml.org.cn/j2ee/201301074.asp [详解设计模式在Spring中的应用] [http://www.geek521.c ...
- spring 中的设计模式
https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=2247485205&idx=1&sn=63455d2313776d ...
- 详解设计模式在Spring中的应用
设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆. 今天,在IT学习者网站就设计模式的内在价值做一番探讨,并以spring为例进行讲解,只有领略了其设 ...
随机推荐
- MySQL多实例,主从同步
由于背景原因,所做的主从同步还是要基于MySQL 5.1的版本,主从同步主要是一个数据库读写访问原来的数据库热度过大,需要做到使用从库对读分压. MySQL主从同步介绍 MySQL 支持单双向 ...
- [Solution] Microsoft Windows 服务(3) 使用Quartz.net定时任务
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,Quartz.net 就是Quartz的移植版本.Quartz可以用来创建简单或为运行十个,百个,甚至是 ...
- 【原创】Silverlight客户端发起WebRequest请求分析
Silverlight网站部署后,客户端浏览器访问的时候会 下载 网站的xap文件包等信息,把程序代码放到本地执行,因为本地机器上安装了silverlight运行库. 所以如果silverlight前 ...
- Ubuntu系统操作快捷键
Ubuntu操作基本快捷键* 打开主菜单 = Alt + F1* 运行 = Alt + F2* 显示桌面 = Ctrl + Alt + d* 最小化当前窗口 = Alt + F9* 最大化当前窗口 = ...
- Foreach能够循环的本质
我们对foreach循环并不陌生,在C#中我们用得非常多,但是我们是否清楚foreach循环的本质呢? 众所周知,foreach循环能够遍历 数组 ,集合 .但是我们自己定义的一个类是否能够通过fo ...
- jquery ajax跨域访问webservice配置
1.webservice方法 [System.Web.Script.Services.ScriptService] public class TestService : System.Web.Serv ...
- 1. windows环境安装Node.js
1. 下载 地址: https://nodejs.org/en/ 2. 下载最新版本v6.1.0 Currrent
- 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性
[源码下载] 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性 作者:webabcd 介绍重新想象 Windows 8.1 Store Ap ...
- 与众不同 windows phone (41) - 8.0 相机和照片: 通过 AudioVideoCaptureDevice 捕获视频和音频
[源码下载] 与众不同 windows phone (41) - 8.0 相机和照片: 通过 AudioVideoCaptureDevice 捕获视频和音频 作者:webabcd 介绍与众不同 win ...
- spring注解配置启动过程
最近看起spring源码,突然想知道没有web.xml的配置,spring是怎么通过一个继承于AbstractAnnotationConfigDispatcherServletInitializer的 ...