Какие паттерны используются в Spring Framework
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерны в Spring Framework
Spring Framework основан на нескольких фундаментальных паттернах проектирования, которые обеспечивают его мощь и гибкость. Понимание этих паттернов критично для эффективной работы с Spring.
1. Inversion of Control (IoC) паттерн
Это главный паттерн Spring. Вместо того, чтобы ваш код создавал объекты и управлял их жизненным циклом, это делает Spring контейнер.
// Без IoC (плохо)
public class OrderService {
private UserRepository userRepository = new UserRepository();
private EmailService emailService = new EmailService();
public void createOrder(String userId) {
// Жёстко завязано на конкретные реализации
}
}
// С IoC (хорошо)
@Service
public class OrderService {
private final UserRepository userRepository;
private final EmailService emailService;
public OrderService(UserRepository userRepository, EmailService emailService) {
this.userRepository = userRepository;
this.emailService = emailService;
}
}
2. Dependency Injection (DI) паттерн
Часть IoC паттерна. Spring инъецирует зависимости через конструктор, setter или field injection.
// Constructor injection (рекомендуется)
@Service
public class UserService {
private final UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
}
// Setter injection
@Service
public class UserService {
private UserRepository repository;
@Autowired
public void setRepository(UserRepository repository) {
this.repository = repository;
}
}
// Field injection (не рекомендуется)
@Service
public class UserService {
@Autowired
private UserRepository repository;
}
3. Singleton паттерн
По умолчанию Spring создаёт бины как синглтоны — один экземпляр на всё приложение.
@Service
@Scope("singleton") // По умолчанию
public class UserService {
// Один экземпляр на всё приложение
}
// ApplicationContext.getBean() всегда возвращает одно и то же
UserService service1 = context.getBean(UserService.class);
UserService service2 = context.getBean(UserService.class);
assert service1 == service2; // true
4. Factory паттерн
Spring использует Factory паттерн для создания бинов. @Bean методы — это явное применение этого паттерна.
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
return new HikariDataSource(hikariConfig());
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
Фабрика может быть и более сложной:
@Configuration
public class DatabaseFactory {
@Bean
public UserRepository userRepository(DataSource dataSource) {
if (isProduction()) {
return new PostgresUserRepository(dataSource);
} else {
return new MockUserRepository();
}
}
}
5. Proxy паттерн
Spring использует прокси для AOP (Aspect-Oriented Programming). Когда вы применяете @Transactional или @Cacheable, Spring обёртывает ваш бин прокси.
@Service
public class UserService {
@Transactional // Spring создаёт прокси с логикой транзакций
public User createUser(String name) {
// Логика создания пользователя
}
@Cacheable("users")
public User getUser(Long id) {
// Spring кеширует результат
}
}
// Spring создаёт что-то вроде:
public class UserServiceProxy extends UserService {
@Override
public User createUser(String name) {
// Начало транзакции
try {
return super.createUser(name);
} finally {
// Коммит или откат
}
}
}
6. Observer паттерн
Spring Event система основана на Observer паттерне.
// Событие
public class UserCreatedEvent extends ApplicationEvent {
private final String username;
public UserCreatedEvent(Object source, String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
}
// Publisher
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher publisher;
public void createUser(String name) {
// Логика создания
publisher.publishEvent(new UserCreatedEvent(this, name));
}
}
// Observer
@Component
public class EmailNotifier {
@EventListener
public void onUserCreated(UserCreatedEvent event) {
sendEmail(event.getUsername());
}
}
7. Strategy паттерн
Используется для выбора различных реализаций в зависимости от конфигурации.
public interface PaymentStrategy {
void pay(BigDecimal amount);
}
@Component
public class CreditCardPayment implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
// Оплата кредитной картой
}
}
@Component
public class PayPalPayment implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
// Оплата через PayPal
}
}
@Service
public class PaymentProcessor {
private final Map<String, PaymentStrategy> strategies;
public PaymentProcessor(List<PaymentStrategy> strategies) {
this.strategies = strategies.stream()
.collect(Collectors.toMap(s -> s.getClass().getSimpleName(), s -> s));
}
public void process(String method, BigDecimal amount) {
strategies.get(method).pay(amount);
}
}
8. Template Method паттерн
Используется в классах типа JdbcTemplate, RestTemplate.
@Component
public class JdbcUserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new Object[]{id},
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))
);
}
}
9. Decorator паттерн
АOP используется для декорирования методов функциональностью типа логирования, мониторинга.
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Calling method: " + joinPoint.getSignature());
}
}
10. Chain of Responsibility паттерн
Используется в Spring Security для цепи фильтров.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/");
}
}
Итоги
Spring Framework использует множество паттернов для обеспечения:
- Гибкости — через Dependency Injection
- Расширяемости — через Strategy и Factory паттерны
- Модульности — через разделение ответственности
- Кросскатинга concerns — через AOP
- Асинхронности — через Observer паттерн
Понимание этих паттернов поможет вам писать более качественный и поддерживаемый код в Spring приложениях.