Java for Beginner
672 subscribers
541 photos
155 videos
12 files
827 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Паттерны использования бинов в Spring

Spring предлагает гибкую и мощную инфраструктуру для создания и управления бинами. Благодаря использованию различных паттернов проектирования, таких как Factory, Service Locator, Dependency Injection, разработчики могут строить приложения, которые легко поддерживать и расширять.

1. Паттерн Factory (Фабрика)

Паттерн Factory представляет собой подход, при котором создание объектов делегируется фабричным методам. Это особенно полезно, когда объект требует сложной логики для инициализации. В Spring фабрики часто используются для создания бинов с нестандартными параметрами или сложной логикой конфигурации.

Пример фабрики в Spring

Создадим фабрику, которая будет возвращать объекты MessageService с различными типами отправки сообщений:
public class MessageServiceFactory {

public static MessageService createMessageService(String type) {
if ("email".equalsIgnoreCase(type)) {
return new EmailService();
} else if ("sms".equalsIgnoreCase(type)) {
return new SmsService();
}
throw new IllegalArgumentException("Неизвестный тип сервиса: " + type);
}
}


Использование фабрики в
Spring:
<bean id="messageService" class="com.example.MessageServiceFactory" factory-method="createMessageService">
<constructor-arg value="email"/>
</bean>
В этом примере бин MessageService создается с помощью фабрики, и мы можем легко изменять его тип без необходимости изменения основного кода.


2. Паттерн Service Locator (Локатор Сервисов)

Service Locator — это паттерн, который позволяет получить необходимые зависимости через централизованный компонент. В Spring этот паттерн реализуется через ApplicationContext, который предоставляет методы для получения бинов по их типу или имени.

Пример Service Locator
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ServiceLocatorExample {

public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// Получаем бин по его типу
MessageService service = context.getBean(MessageService.class);
service.sendMessage("Сообщение через Service Locator");
}
}
Паттерн Service Locator хорош, когда необходимо динамически получать зависимости, но следует быть осторожным, чтобы не злоупотреблять этим паттерном, так как он может нарушить принципы инверсии управления.


3. Паттерн Dependency Injection (Внедрение Зависимостей)

Dependency Injection (DI) — это основной паттерн, на котором строится Spring. Он позволяет передавать зависимости объекту через конструктор, сеттеры или интерфейсы. Внедрение зависимостей способствует слабой связанности кода, что упрощает его тестирование и сопровождение.

Пример внедрения через конструктор
@Component
public class MessageService {
private final NotificationService notificationService;

@Autowired
public MessageService(NotificationService notificationService) {
this.notificationService = notificationService;
}

public void sendMessage(String message) {
notificationService.notify(message);
}
}
Здесь зависимость NotificationService внедряется в конструктор класса MessageService.


Пример внедрения через сеттер
@Component
public class MessageService {
private NotificationService notificationService;

@Autowired
public void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}

public void sendMessage(String message) {
notificationService.notify(message);
}
}


Оба способа обеспечивают слабую связанность между компонентами и делают систему более гибкой для тестирования и изменения.

#Java #Training #Spring #Spring_Patterns
4. Паттерн Proxy (Заместитель)

Паттерн Proxy используется для управления доступом к объекту или для добавления дополнительной логики перед вызовом методов.

Пример использования Proxy через AOP

Spring AOP позволяет легко внедрять кросс-каттинговые (перекрёстные) задачи, такие как логирование, безопасность, или управление транзакциями.
@Aspect
@Component
public class LoggingAspect {

@Before("execution(* com.example.service.*.*(..))")
public void logBeforeMethod(JoinPoint joinPoint) {
System.out.println("Вызов метода: " + joinPoint.getSignature().getName());
}
}
Здесь мы создаём аспект (Aspect), который использует прокси для добавления логирования перед вызовом любого метода в указанном пакете.


5. Паттерн Template Method (Шаблонный Метод)

Template Method позволяет определять алгоритм в суперклассе, оставляя определённые шаги для реализации в подклассах. В Spring этот паттерн реализован в различных helper-классах, например, JdbcTemplate, RestTemplate, где основная логика выполнения операции обобщена.

Пример использования JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;

public void addUser(String name, int age) {
String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
jdbcTemplate.update(sql, name, age);
}
Здесь JdbcTemplate инкапсулирует шаблонный метод для выполнения SQL-запросов, а детали (вроде обработки исключений или управления транзакциями) обрабатываются внутри JdbcTemplate.


8. Паттерн Observer (Наблюдатель)

Паттерн Observer (Наблюдатель) используется для реализации механизма подписки-уведомления, где один объект (Subject) уведомляет множество наблюдателей (Observers) о событиях. В Spring этот паттерн реализован через события (Event), которые могут быть опубликованы и обработаны компонентами.

Пример реализации событий в Spring
// Определение события
public class UserCreatedEvent extends ApplicationEvent {
private String username;

public UserCreatedEvent(Object source, String username) {
super(source);
this.username = username;
}

public String getUsername() {
return username;
}
}

// Публикация события
@Component
public class UserService {

@Autowired
private ApplicationEventPublisher eventPublisher;

public void createUser(String username) {
System.out.println("Создание пользователя: " + username);
eventPublisher.publishEvent(new UserCreatedEvent(this, username));
}
}

// Обработчик события
@Component
public class UserEventListener {

@EventListener
public void handleUserCreated(UserCreatedEvent event) {
System.out.println("Пользователь создан: " + event.getUsername());
}
}
Здесь UserService публикует событие UserCreatedEvent, которое обрабатывается компонентом UserEventListener.


7. Паттерн Strategy (Стратегия)

Паттерн Strategy позволяет определять семейство алгоритмов, инкапсулировать их и сделать их взаимозаменяемыми. В Spring этот паттерн часто используется через внедрение зависимостей, где определённая стратегия передаётся в виде бина.

Пример реализации паттерна Strategy
public interface NotificationStrategy {
void send(String message);
}

@Component
public class EmailNotification implements NotificationStrategy {
public void send(String message) {
System.out.println("Отправка email: " + message);
}
}

@Component
public class SmsNotification implements NotificationStrategy {
public void send(String message) {
System.out.println("Отправка SMS: " + message);
}
}

@Component
public class NotificationService {

private final NotificationStrategy notificationStrategy;

@Autowired
public NotificationService(NotificationStrategy notificationStrategy) {
this.notificationStrategy = notificationStrategy;
}

public void sendNotification(String message) {
notificationStrategy.send(message);
}
}
В этом примере стратегия уведомлений может быть легко изменена путем внедрения различных реализаций интерфейса NotificationStrategy.


#Java #Training #Spring #Spring_Patterns