← Назад к вопросам

Как используется паттерн "Шаблонный метод" в Spring

2.0 Middle🔥 61 комментариев
#SOLID и паттерны проектирования#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Как используется паттерн "Шаблонный метод" в Spring

Что такое Template Method

Template Method — это поведенческий паттерн, который определяет скелет алгоритма в базовом классе, позволяя подклассам переопределять отдельные шаги без изменения структуры алгоритма.

Использование в Spring Framework

Spring Framework активно использует этот паттерн в ядре, создавая гибкие абстракции для расширения функциональности.

1. JdbcTemplate — основной пример

Одна из самых известных реализаций Template Method в Spring:

public abstract class JdbcOperations {
    // Шаблонный метод
    public <T> T execute(String sql, PreparedStatementCallback<T> action) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);
            return action.doInPreparedStatement(pstmt);
        } catch (SQLException e) {
            throw new DataAccessException("DB Error", e);
        } finally {
            close(pstmt, conn);
        }
    }
}

String result = jdbcTemplate.query(
    "SELECT * FROM users WHERE id = ?",
    new PreparedStatementCallback<String>() {
        @Override
        public String doInPreparedStatement(PreparedStatement pstmt) 
                throws SQLException {
            pstmt.setInt(1, userId);
            ResultSet rs = pstmt.executeQuery();
            return rs.getString("name");
        }
    }
);

2. RestTemplate

public class RestTemplate extends InterceptingHttpAccessor 
        implements RestOperations {
    
    private <T> T execute(String url, HttpMethod method, 
            RequestCallback requestCallback,
            ResponseExtractor<T> responseExtractor) {
        HttpMessageConverter[] converters = getMessageConverters();
        ClientHttpResponse response = null;
        try {
            ClientHttpRequest request = createRequest(url, method);
            requestCallback.doWithRequest(request);
            response = request.execute();
            return responseExtractor.extractData(response);
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }
}

String result = restTemplate.getForObject(
    "https://api.example.com/users/{id}",
    String.class,
    userId
);

3. Собственная реализация Template Method

public abstract class DataProcessor<T> {
    
    public final void processData(List<T> data) {
        try {
            List<T> validated = validate(data);
            List<T> transformed = transform(validated);
            List<T> enriched = enrich(transformed);
            save(enriched);
            notifySuccess();
        } catch (Exception e) {
            handleError(e);
        }
    }
    
    protected abstract List<T> validate(List<T> data);
    protected abstract List<T> transform(List<T> data);
    
    protected List<T> enrich(List<T> data) {
        return data;
    }
    
    protected void save(List<T> data) {
        // Сохраняем в БД
    }
    
    protected void notifySuccess() {
        System.out.println("Processing completed");
    }
    
    protected void handleError(Exception e) {
        e.printStackTrace();
    }
}

@Service
public class UserDataProcessor extends DataProcessor<User> {
    
    @Override
    protected List<User> validate(List<User> data) {
        return data.stream()
            .filter(u -> u.getEmail() != null && u.getAge() >= 18)
            .collect(Collectors.toList());
    }
    
    @Override
    protected List<User> transform(List<User> data) {
        return data.stream()
            .peek(u -> u.setEmail(u.getEmail().toLowerCase()))
            .collect(Collectors.toList());
    }
}

@RestController
public class UserController {
    @Autowired
    private UserDataProcessor processor;
    
    @PostMapping("/users/batch")
    public ResponseEntity<?> processBatch(@RequestBody List<User> users) {
        processor.processData(users);
        return ResponseEntity.ok("Processed");
    }
}

Преимущества Template Method в Spring

✓ Инверсия управления — фреймворк управляет ресурсами, код занимается логикой ✓ DRY принцип — повторяющаяся логика в одном месте ✓ Консистентность — все компоненты следуют одному паттерну ✓ Простота расширения — новые реализации просто переопределяют нужные методы ✓ Безопасность — корректное управление ресурсами гарантировано

Spring Data Repository

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByEmail(String email);
}

Под капотом JpaRepository реализует Template Method для управления транзакциями и кешированием.

Template Method — один из наиболее часто используемых паттернов в Spring, скрытый от разработчика, но критически важный для надежной работы приложения.