Как используется паттерн "Шаблонный метод" в Spring
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Как используется паттерн "Шаблонный метод" в 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, скрытый от разработчика, но критически важный для надежной работы приложения.