Какой используется паттерн при создании Bean?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерны создания Bean в Spring Framework
Pри создании объектов (Bean) в Spring используется несколько паттернов проектирования, главный из которых — Factory Pattern, но также применяются другие.
1. Factory Pattern (основной)
Spring использует Factory Pattern для создания Bean'ов. Это позволяет абстрагировать логику создания объектов.
// Пример: Spring сам выступает как Factory
public interface BeanFactory {
Object getBean(String name);
<T> T getBean(Class<T> requiredType);
}
@Configuration
public class AppConfig {
// Spring использует эту фабрику (метод) для создания Bean
@Bean
public UserService userService() {
// Логика создания
UserService service = new UserService();
service.init(); // инициализация
return service;
}
}
// Использование
BeanFactory beanFactory = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = beanFactory.getBean(UserService.class);
2. Singleton Pattern
По умолчанию все Bean'ы в Spring — Singleton (одного экземпляра на приложение).
@Component
@Scope("singleton") // По умолчанию
public class UserRepository {
// Один экземпляр на приложение
// Все инъекции получают одну и ту же ссылку
}
private static UserRepository instance; // Внутри Spring
public static UserRepository getInstance() {
if (instance == null) {
instance = new UserRepository();
}
return instance;
}
Проблема и решение:
// ❌ ПРОБЛЕМА: Singleton с состоянием (not thread-safe)
@Component
public class UserSessionHolder {
private User currentUser; // Общее для всех потоков!
public void setUser(User user) {
this.currentUser = user;
}
}
// ✅ РЕШЕНИЕ: Использовать Prototype или Request scope
@Component
@Scope("request")
public class UserSessionHolder {
private User currentUser; // Отдельно для каждого запроса
}
3. Dependency Injection Pattern
Spring реализует DI (Dependency Injection), а именно:
Constructor Injection (рекомендуется)
@Service
public class OrderService {
private final UserRepository userRepository;
private final PaymentService paymentService;
// Инъекция через конструктор
public OrderService(UserRepository userRepository,
PaymentService paymentService) {
this.userRepository = userRepository;
this.paymentService = paymentService;
}
}
// Spring автоматически вызывает конструктор с нужными параметрами
Setter Injection
@Service
public class OrderService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Field Injection (не рекомендуется)
@Service
public class OrderService {
@Autowired
private UserRepository userRepository; // Spring инъектирует автоматически
}
4. Builder Pattern
Spring использует Builder для создания сложных объектов, например DataSource:
// Builder для DataSource
DataSource dataSource = DataSourceBuilder.create()
.driverClassName("org.postgresql.Driver")
.url("jdbc:postgresql://localhost:5432/mydb")
.username("user")
.password("pass")
.build();
// Или в Bean методе
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create()
.driverClassName("org.postgresql.Driver")
.url("jdbc:postgresql://localhost/mydb")
.build();
}
5. Template Method Pattern
Spring использует Template Method для жизненного цикла Bean'ов:
@Component
public class MyBean {
// Template Method паттерн: Spring вызывает эти методы в определённом порядке
@PostConstruct
public void init() {
System.out.println("1. Bean инициализирован");
}
public void doSomething() {
System.out.println("2. Bean работает");
}
@PreDestroy
public void destroy() {
System.out.println("3. Bean уничтожается");
}
}
// Жизненный цикл:
// 1. Создание объекта (Constructor)
// 2. @PostConstruct
// 3. Использование
// 4. @PreDestroy
6. Strategy Pattern
Выбор стратегии на основе условий:
// Различные реализации платёжных систем
public interface PaymentGateway {
void process(double amount);
}
@Component("stripe")
public class StripePaymentGateway implements PaymentGateway {
@Override
public void process(double amount) { /* Stripe логика */ }
}
@Component("paypal")
public class PayPalPaymentGateway implements PaymentGateway {
@Override
public void process(double amount) { /* PayPal логика */ }
}
// Spring выбирает реализацию
@Service
public class OrderService {
@Autowired
@Qualifier("stripe") // Выбираем стратегию
private PaymentGateway paymentGateway;
}
7. Proxy Pattern
Spring использует прокси для создания bean'ов (особенно с @Transactional):
@Service
public class UserService {
@Transactional // Spring создаёт Proxy вокруг UserService
public void saveUser(User user) {
// Proxy добавляет логику управления транзакциями
// Реальный сервис вызывается через proxy
}
}
// Что происходит внутри:
// UserService service = new UserService();
// UserService proxy = new Proxy(service); // обёртка с доп функционалом
// proxy.saveUser(user); // вызовет логику транзакций, потом реальный сервис
8. Adapter Pattern
адаптирует компоненты с разными интерфейсами:
// Старый интерфейс
public interface OldUserService {
User getUserById(int id);
}
// Новый интерфейс
public interface NewUserService {
User getUser(Long id);
}
// Адаптер
@Component
public class UserServiceAdapter implements NewUserService {
@Autowired
private OldUserService oldService;
@Override
public User getUser(Long id) {
return oldService.getUserById(id.intValue());
}
}
9. Observer Pattern (Event-Driven)
Spring использует для событий:
// Событие
public class UserCreatedEvent extends ApplicationEvent {
private User user;
public UserCreatedEvent(Object source, User user) {
super(source);
this.user = user;
}
}
// Издатель события
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createUser(User user) {
userRepository.save(user);
eventPublisher.publishEvent(new UserCreatedEvent(this, user));
}
}
// Слушатель события
@Component
public class EmailNotificationListener {
@EventListener
public void onUserCreated(UserCreatedEvent event) {
emailService.sendWelcome(event.getUser().getEmail());
}
}
10. Abstract Factory Pattern
Создание семейств связанных объектов:
// Abstract Factory
public interface DataSourceFactory {
DataSource createDataSource();
ConnectionPool createConnectionPool();
}
@Configuration
@Profile("prod")
public class ProdDataSourceFactory implements DataSourceFactory {
@Override
public DataSource createDataSource() { /* Prod DataSource */ }
@Override
public ConnectionPool createConnectionPool() { /* Prod Pool */ }
}
@Configuration
@Profile("dev")
public class DevDataSourceFactory implements DataSourceFactory {
@Override
public DataSource createDataSource() { /* H2 DataSource */ }
@Override
public ConnectionPool createConnectionPool() { /* Dev Pool */ }
}
Жизненный цикл Bean'а (все паттерны в действии)
@Configuration
public class BeanLifecycleExample {
@Bean
public MyService myService() {
// 1. Factory Pattern: фабрика создаёт объект
return new MyService();
}
}
@Component
public class MyService implements InitializingBean, DisposableBean {
// 2. Constructor
public MyService() {
System.out.println("1. Конструктор");
}
// 3. Setter Injection
@Autowired
public void setDependency(Dependency dep) {
System.out.println("2. Injection");
}
// 4. InitializingBean / @PostConstruct (Template Method)
@PostConstruct
public void init() {
System.out.println("3. Инициализация");
}
// 5. DisposableBean / @PreDestroy
@PreDestroy
public void destroy() {
System.out.println("4. Уничтожение");
}
}
Выводы
| Паттерн | Где использует Spring |
|---|---|
| Factory | Bean creation |
| Singleton | Default scope |
| Dependency Injection | @Autowired, Constructor |
| Builder | DataSourceBuilder |
| Template Method | Bean lifecycle |
| Strategy | @Qualifier for implementations |
| Proxy | @Transactional, AOP |
| Adapter | Integrations |
| Observer | ApplicationEvent |
| Abstract Factory | Profiles, Conditional beans |
Основной паттерн — Factory, но Spring применяет множество паттернов вместе для создания гибкой и мощной системы управления компонентами.