前面已经说过命令模式,现在我们来看看spring框架中JdbcTemplate中使用的命令模式

首先先注入jdbctemplate 调用 queryForObject 方法

其实每个方法底层实现都一样,就用这个举例吧。点进去这个方法,一路跟进去,找到最深那个query方法

在中间一直都在构建查询需要的参数,可以跳过,最深的query方法如下

@Override
    @Nullable
    public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        Assert.notNull(rse, "ResultSetExtractor must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL query [" + sql + "]");
        }

        class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
            @Override
            @Nullable
            public T doInStatement(Statement stmt) throws SQLException {
                ResultSet rs = null;
                try {
                    rs = stmt.executeQuery(sql);
                    return rse.extractData(rs);
                }
                finally {
                    JdbcUtils.closeResultSet(rs);
                }
            }
            @Override
            public String getSql() {
                return sql;
            }
        }

        return execute(new QueryStatementCallback());
    }

这里面有个内部类  QueryStatementCallback  实现了  StatementCallback 接口

而这个接口只有一个方法

@Nullable
    T doInStatement(Statement stmt) throws SQLException, DataAccessException;

通过类图可以看到这个接口还有好几个具体实现类

 上面说的QueryStatementCallback 只是其中一个,然后我们看看这个类具体实现方法  doInStatement 

本质上就是调用这个方法的参数的 executeQuery 方法 执行sql。

最后就是创建了这个内部类的实例传给 execute方法 ,点进去,

     @Override
     @Nullable
     public <T> T execute(StatementCallback<T> action) throws DataAccessException {
         Assert.notNull(action, "Callback object must not be null");
 
         Connection con = DataSourceUtils.getConnection(obtainDataSource());
         Statement stmt = null;
         try {
             stmt = con.createStatement();
             applyStatementSettings(stmt);
             T result = action.doInStatement(stmt);
             handleWarnings(stmt);
             return result;
         }
         catch (SQLException ex) {
             // Release Connection early, to avoid potential connection pool deadlock
             // in the case when the exception translator hasn't been initialized yet.
             String sql = getSql(action);
             JdbcUtils.closeStatement(stmt);
             stmt = null;
             DataSourceUtils.releaseConnection(con, getDataSource());
             con = null;
             throw translateException("StatementCallback", sql, ex);
         }
         finally {
             JdbcUtils.closeStatement(stmt);
             DataSourceUtils.releaseConnection(con, getDataSource());
         }
     }

第11行,就是调用真正内部类的实现,在调用之前,需要构建方法所需参数stmt , 然后返回结果

那怎么和命令模式联系起来呢?我们来和命令模式5种角色,对号入座:

Command 其实 就是  StatementCallback ,里面的doInStatement就是 命令方法。

CommandImpl  就是  QueryStatementCallback ,由命令的具体实现去调用真正的执行方法,真正的执行方法就是stmt的executeQuery()。

Receiver 呢?jdbctemplate 是没有具体的,但是我们可以把 Statement 看做是这个receiver ,前面的命令模式说的是,命令的具体实现拥有接收者,并通过构造方法赋值,而template 它是把接收者当作参数传递,我觉得本质是一样的

  因为之前实例化命令的具体实现时,传入接收者,当然先的构造一个接收者,而template 也是一样,先构造statement 然后传入。

Invoker 就相当于  public <T> T execute(StatementCallback<T> action) throws DataAccessException 这个方法。

Client 就相当于我们自己开发的应用程序。

可以看出这个invokrer 也是传入不同的具体命令,执行不同的 命令,达到不一样的结果。

参考了一些大佬的博客,结合自己的见解,如果有不对的地方,请指出哈。

 

转载于:https://www.cnblogs.com/longyao/p/12576119.html