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的结合使用浅析的更多相关文章

  1. (转)Spring中Singleton模式的线程安全

    不知道哪里的文章,总结性还是比较好的.但是代码凌乱,有的还没有图.如果找到原文了可以进行替换! spring中的单例 spring中管理的bean实例默认情况下是单例的[sigleton类型],就还有 ...

  2. Spring中常用的23中设计模式

    1.spring 中常用的设计模式有23中  分类  设计模式  创建型 工厂方法模式(FactoryMethod).抽象工厂模式(AbstractFactory).建造者模式(Builder).原型 ...

  3. Spring中使用的设计模式

    目录 Spring使用的设计模式 1.单例模式 2.原型模式 3.模板模式 4.观察者模式 5.工厂模式 简单工厂模式 工厂方法模式 6.适配器模式 7.装饰者模式 8.代理模式 9.策略模式   S ...

  4. [转] 9种设计模式在Spring中的运用

    作者:iCoding91地址:https://blog.csdn.net/caoxiaohong1005 转发的公众号地址,有其他设计模式介绍:https://mp.weixin.qq.com/s/Z ...

  5. 9种设计模式在Spring中的运用,一定要非常熟练

    1.简单工厂(非23种设计模式中的一种) 实现方式: BeanFactory.Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数 ...

  6. Spring中的设计模式学习

    Spring提供了一种Template的设计哲学,包含了很多优秀的软件工程思想. 1. 简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. ...

  7. Spring中的设计模式

    [Spring中的设计模式] http://www.uml.org.cn/j2ee/201301074.asp [详解设计模式在Spring中的应用]    [http://www.geek521.c ...

  8. spring 中的设计模式

    https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=2247485205&idx=1&sn=63455d2313776d ...

  9. 详解设计模式在Spring中的应用

    设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆. 今天,在IT学习者网站就设计模式的内在价值做一番探讨,并以spring为例进行讲解,只有领略了其设 ...

随机推荐

  1. (8)分布式下的爬虫Scrapy应该如何做-图片下载(源码放送)

      转载主注明出处:http://www.cnblogs.com/codefish/p/4968260.html 在爬虫中,我们遇到比较多需求就是文件下载以及图片下载,在其它的语言或者框架中,我们可能 ...

  2. Linux下修改PATH路径

    1.#PATH=$PATH:/opt/lamp/mysql/bin       使用这种方法,只对当前会话有效,也就是说每当登出或注销系统以后,PATH 设置就会失效 2.#vi /etc/profi ...

  3. 使用Architecture Explorer分析应用程序及使用层次图

    使用Architecture Explorer分析应用程序 Architecture Explorer和依赖图可以帮助我们了解所有的项目,包括小项目和大项目.Architecture Explorer ...

  4. 2015年百度之星初赛(1) --- B 找连续数

    找连续数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. Linq专题之查询操作

    前面我们主要讲解的是Linq的查询表达式,Linq不但提供了一些基本的查询表达式,还提供了数十个查询操作.比如筛选操作.聚合操作.投影操作等等.通过这些查询操作可以更方便的对数据源进行处理. Linq ...

  6. 基于Lumisoft.NET组件的SMTP账号登陆检测

    在邮件处理的方面,Lumisoft.NET可以说是非常不错的一个选择,我在前面几篇文章中都介绍过这个组件. 基于Lumisoft.NET组件开发碰到乱码等一些问题的解决 基于Lumisoft.NET组 ...

  7. DataGridView隐藏列用CSS实现

    隐藏DataGridView某一列,用CSS控制 CSS Code: .hidden{ display:none;} c# Code: <asp:BoundField DataField=&qu ...

  8. CSS行高line-height的理解

    一.行高的字面意思 “行高“顾名思义指一行文子的高度.具体来说是指两行文子间基线间的距离. 基线是在英文字母中用到的一个概念,我们刚学英语的时候使用到的那个英语本子每行有4条线,其中底部第二条线就是基 ...

  9. 如何弹出一定的大小的web窗体?

    如何弹出一定的大小的web窗体?  摘自: http://blog.163.com/hweibin126@126/blog/static/17044246920108413348344/ 一.wind ...

  10. 重新想象 Windows 8 Store Apps 系列文章索引

    [源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...