之前在看《Spring揭秘》的时候,发现了Spring处理数据库的精髓类JdbcTemplate,它使用了模板的设计模式,即将流程固定化,比如数据库连接的获取,数据库连接的关闭等,然后将变化的部分交由子类或者回调函数实现。
以前接触的都是抽象父类声明流程,流程中包含抽象函数,子类继承父类并实现父类的抽象函数,这样父类的流程这个流程是不变的,变的只是子类的抽象方法的实现。但是这个的基础是继承,如果你变化的部分太多,你要实现很多很多类,而且如果父类的流程有多个,那子类要实现自己并不需要的抽象函数,这是一个弊端。
Spring在几个*Template的类中使用回调函数的方式,比如下面是JdbcTemplate的方法:
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(this.getDataSource());
Statement stmt = null;
Object var7;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
stmt = conToUse.createStatement();
this.applyStatementSettings(stmt);
Statement stmtToUse = stmt;
if (this.nativeJdbcExtractor != null) {
stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
}
T result = action.doInStatement(stmtToUse);
this.handleWarnings(stmt);
var7 = result;
} catch (SQLException var11) {
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, this.getDataSource());
con = null;
throw this.getExceptionTranslator().translate("StatementCallback", getSql(action), var11);
} finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, this.getDataSource());
}
return var7;
}
可以发现,它的参数是StatementCallback<T> action,以CallBack结尾,可以看到这是个接口,接口定义了一个方法,这个方法就是被流程调用的:
package org.springframework.jdbc.core;
import java.sql.SQLException;
import java.sql.Statement;
import org.springframework.dao.DataAccessException;
public interface StatementCallback<T> {
T doInStatement(Statement var1) throws SQLException, DataAccessException;
}
只要继承并实现自己的需要实现的方法就可以了,这样在多个流程的情况下,你不需要实现自己不需要的方法。
除此之外,还发现了两个类似的类:事务处理的TransactionTemplate以及处理redis的RedisTemplate,都使用了类似的方式。比如前者:
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this, action);
} else {
TransactionStatus status = this.transactionManager.getTransaction(this);
Object result;
try {
result = action.doInTransaction(status);
} catch (RuntimeException var5) {
this.rollbackOnException(status, var5);
throw var5;
} catch (Error var6) {
this.rollbackOnException(status, var6);
throw var6;
} catch (Throwable var7) {
this.rollbackOnException(status, var7);
throw new UndeclaredThrowableException(var7, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
package org.springframework.transaction.support;
import org.springframework.transaction.TransactionStatus;
public interface TransactionCallback<T> {
T doInTransaction(TransactionStatus var1);
}
它的实现类:
package org.springframework.transaction.support;
import org.springframework.transaction.TransactionStatus;
public abstract class TransactionCallbackWithoutResult implements TransactionCallback<Object> {
public TransactionCallbackWithoutResult() {
}
public final Object doInTransaction(TransactionStatus status) {
this.doInTransactionWithoutResult(status);
return null;
}
protected abstract void doInTransactionWithoutResult(TransactionStatus var1);
}
下面是调用的一个代码片段:
int propagation = newTxRequired ? 3 : 0;
TransactionAttribute transactionAttribute = TestContextTransactionUtils.createDelegatingTransactionAttribute(testContext, new DefaultTransactionAttribute(propagation));
(new TransactionTemplate(transactionManager, transactionAttribute)).execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
populator.execute(dataSource);
}
});
使用匿名内部类,不过这些CallBack类大部分都是函数式接口,以后可以使用Lambda表达式来实现。
补充,又发现一个类似的:
在spring-jms中的JmsTemplate以及其中的eecute方法,在查看*Callback的接口时,如果你想查看它的具体实现,大部分是匿名内部类,比如SessionCallback:
这1,2…都是匿名内部类,比如:
public <T> T execute(final Destination destination, final ProducerCallback<T> action) throws JmsException {
Assert.notNull(action, "Callback object must not be null");
return this.execute(new SessionCallback<T>() {
public T doInJms(Session session) throws JMSException {
MessageProducer producer = JmsTemplate.this.createProducer(session, destination);
Object var3;
try {
var3 = action.doInJms(session, producer);
} finally {
JmsUtils.closeMessageProducer(producer);
}
return var3;
}
}, false);
}
————————————————
版权声明:本文为CSDN博主「幺零小柒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a_842297171/article/details/81746307