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为例进行讲解,只有领略了其设 ...
随机推荐
- sql server 查找包含字符串的对象
sql server 查找包含字符串的对象 SELECT sm.object_id, OBJECT_NAME(sm.object_id) AS object_name, o.type, o.type_ ...
- Linq查询操作之投影操作
投影操作,乍一看不知道在说啥.那么什么是投影操作呢?其实就是Select操作,名字起的怪怪的.和Linq查询表达式中的select操作是一样的.它能够选择数据源中的元素,并指定元素的表现形式.投影操作 ...
- C#实用杂记-EF全性能优化技巧
原文链接:http://www.makmong.com/947.html#comment-31 EntityFramework 优化建议 2016年1月15日 下午4:54 LEILINKANG ...
- 使用栈Stack对整数数值的运算表达式字符串进行运算C#
这里如果对于形如字符串“((6+((7+8)-9)*9+8/2)-3)/2”的运算表达式进行运算.接触过此类的同学知道这种存在着运算符优先级的表达式,不能直接从左到右进行运算,我们使用OperandS ...
- 序列中找子序列的dp
题目网址: http://codeforces.com/problemset/problem/414/B Description Mashmokh's boss, Bimokh, didn't lik ...
- 一个web页面的访问的过程
Browers是如何在浩瀚的互联网上找到我们需要的资源呢? 以下将记录这个过程,这个过程是web编程需要需要熟知的. 用户打开浏览器输入目标地址(比如http://www.sina.com),那么接下 ...
- Android小项目合集(经典教程)包含十五个Android开发应用实例
http://www.cnblogs.com/aimeng/archive/2012/03/28/2422435.html
- Webform(分页、组合查询)
一.分页 1.写查询方法: public List<Student> Select(int PageCount, int PageNumber) {//PageCount为每页显示条数,P ...
- css 负边距 小记
水平格式化 当我们在元素上设置width的时候,影响的是内容区的宽度 但是当我们又为元素指定指定了内边距 边框 外边距 还是会增加宽度值 (IE传统盒模型 内边距 边框 会在元素的宽度内扩展 ma ...
- art-template引擎模板
art-template简介 artTemplate(后文简称aT)才是模板引擎,而TmodJS(后文简称TJ,曾用名atc)则是依赖于前者的一款模板预编译器.两者都是由腾讯开发.其实aT完全可以独立 ...