优秀的编程知识分享平台

网站首页 > 技术文章 正文

二十九、Spring 中的模板方法模式深度解析

nanyue 2025-03-10 18:59:41 技术文章 55 ℃

Spring 的模板方法模式通过定义算法骨架和子类扩展点,实现了代码复用和逻辑解耦。它在 Spring 框架中的应用(如 JdbcTemplate、RestTemplate)极大地简化了开发者的工作。掌握模板方法模式的设计思想和最佳实践,能够显著提升代码的可维护性和扩展性。

1. Spring 模板方法模式的核心特点

定义算法骨架:将算法的核心流程固定,具体步骤由子类实现。

代码复用:通过抽象类或接口实现通用逻辑的复用,减少重复代码。

扩展性:子类可以通过重写特定方法扩展或修改算法行为。

与 Spring 集成:模板方法模式广泛应用于 Spring 的框架设计中(如 JdbcTemplate、RestTemplate)。


2. Spring 版本与源码获取

版本:Spring Framework 5.3.26(长期支持版本)

源码下载

Maven 依赖:

 
  org.springframework 
	spring-context
  5.3.26 

直接下载地址:Spring Framework 5.3.26 Release

调试技巧

关键断点位置:JdbcTemplate.execute() → JdbcTemplate.query() → RowMapper.mapRow()。

观察模板方法模式的核心类(如 JdbcTemplate、RestTemplate)。


3. 源码级实现剖析

// 核心类:JdbcTemplate
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
    public  T query(String sql, RowMapper rowMapper) throws DataAccessException {
        return execute(sql, new PreparedStatementCallback() {
            @Override
            public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
                ResultSet rs = ps.executeQuery();
                List results = new ArrayList<>();
                int rowNum = 0;
                while (rs.next()) {
                    results.add(rowMapper.mapRow(rs, rowNum++)); // 调用子类实现的 mapRow 方法
                }
                return results.isEmpty() ? null : results.get(0);
            }
        });
    }
}
  • 比喻:模板方法像一个“烹饪食谱”,定义了做菜的步骤(如洗菜、切菜、炒菜),但具体操作(如切菜方式)由子类实现。

4. 模板方法模式的多维度应用

Spring 中的经典实现

JdbcTemplate

jdbcTemplate.query("SELECT * FROM users", new RowMapper() {
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
        return new User(rs.getString("name"), rs.getInt("age"));
    }
});

RestTemplate

restTemplate.execute("http://example.com", HttpMethod.GET, null, new ResponseExtractor() {
    @Override
    public String extractData(ClientHttpResponse response) throws IOException {
        return StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
    }
});

自定义模板方法

public abstract class DataProcessor {
    // 模板方法:定义算法骨架
    public final void process() {
        openConnection();
        processData();
        closeConnection();
    }

    protected abstract void processData(); // 子类实现具体逻辑

    private void openConnection() { /* 通用逻辑 */ }
    private void closeConnection() { /* 通用逻辑 */ }
}

5. 模板方法模式 vs 策略模式

场景

模板方法模式

策略模式

算法结构

固定算法骨架,子类实现部分步骤

完全替换算法实现

扩展性

通过子类扩展

通过替换策略扩展

与 Spring 集成

适用于固定流程的场景(如 JDBC 操作)

适用于动态切换场景(如支付方式)


6. 实际应用场景

  • 数据库操作:JdbcTemplate 封装了 JDBC 的通用逻辑(如连接管理、异常处理)。
  • HTTP 请求:RestTemplate 封装了 HTTP 请求的通用逻辑(如请求构建、响应解析)。
  • 任务调度:TaskExecutor 定义了任务执行的通用流程,具体任务由子类实现。
  • 文件处理:定义文件读取的通用流程(如打开文件、读取数据、关闭文件),具体解析逻辑由子类实现。

7. 源码调试与陷阱规避

  • 调试步骤
  • 在 JdbcTemplate.query() 或 RestTemplate.execute() 设置断点。
  • 观察模板方法的执行流程(如 openConnection() → processData() → closeConnection())。
  • 常见陷阱
    • 过度抽象:模板方法模式适用于固定流程的场景,过度使用会导致代码复杂度增加。
    • 子类依赖:子类需要了解父类的实现细节,可能导致紧耦合。

8. 性能与最佳实践

  • 优点
    • 提高代码复用性,减少重复代码。
    • 提供清晰的算法结构,便于维护和扩展。
  • 优化建议
    • 尽量减少模板方法的复杂度(如将通用逻辑拆分为独立方法)。
    • 使用钩子方法(Hook Method)提供扩展点,避免子类重写整个方法。
最近发表
标签列表