Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Listeners (Слушатели) в Java
Это фундаментальный паттерн для обработки событий (Event-Driven Architecture). Очень распространён в UI и асинхронных системах.
1. Основы: Observer Pattern
Listener — это реализация паттерна Observer:
// Шаг 1: Определяем интерфейс слушателя (Observer)
public interface ButtonClickListener {
void onButtonClicked(String buttonName);
}
// Шаг 2: Создаём событие (Event Source)
public class Button {
private List<ButtonClickListener> listeners = new ArrayList<>();
private String name;
public Button(String name) {
this.name = name;
}
// Регистрируем слушателя
public void addClickListener(ButtonClickListener listener) {
listeners.add(listener);
}
// Убираем слушателя
public void removeClickListener(ButtonClickListener listener) {
listeners.remove(listener);
}
// Симулируем клик
public void click() {
System.out.println(name + " was clicked");
// Уведомляем всех слушателей
for (ButtonClickListener listener : listeners) {
listener.onButtonClicked(name);
}
}
}
// Шаг 3: Реализуем слушателя (Observer)
public class AlertListener implements ButtonClickListener {
@Override
public void onButtonClicked(String buttonName) {
System.out.println("[Alert] Button clicked: " + buttonName);
}
}
// Шаг 4: Используем
public class Main {
public static void main(String[] args) {
Button btn = new Button("Save");
// Регистрируем несколько слушателей
btn.addClickListener(new AlertListener());
btn.addClickListener(buttonName ->
System.out.println("[Log] Button " + buttonName + " event"));
btn.click();
// Вывод:
// Save was clicked
// [Alert] Button clicked: Save
// [Log] Button Save event
}
}
2. Listeners с Event объектами
Часто передаётся объект события с контекстом:
// Событие
public class ClickEvent {
private final String source;
private final long timestamp;
private final int x, y;
public ClickEvent(String source, int x, int y) {
this.source = source;
this.timestamp = System.currentTimeMillis();
this.x = x;
this.y = y;
}
public String getSource() { return source; }
public long getTimestamp() { return timestamp; }
public int getX() { return x; }
public int getY() { return y; }
}
// Слушатель события
public interface ClickEventListener {
void onEvent(ClickEvent event);
}
// Издатель
public class ClickableComponent {
private List<ClickEventListener> listeners = new ArrayList<>();
public void addListener(ClickEventListener listener) {
listeners.add(listener);
}
public void handleClick(int x, int y) {
ClickEvent event = new ClickEvent("Component", x, y);
for (ClickEventListener listener : listeners) {
listener.onEvent(event);
}
}
}
// Использование
ClickableComponent comp = new ClickableComponent();
comp.addListener(event ->
System.out.println("Clicked at (" + event.getX() + ", " + event.getY() + ")"));
comp.handleClick(100, 200);
3. Listeners в Swing (UI)
Это классический пример использования listeners:
import javax.swing.*;
import java.awt.event.*;
public class SwingListenerExample extends JFrame {
public SwingListenerExample() {
setTitle("Button Listener");
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Click me");
// Добавляем ActionListener
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked!");
}
});
// Или с lambda (Java 8+)
button.addActionListener(e -> System.out.println("Button clicked!"));
add(button);
setVisible(true);
}
}
4. Listeners в Spring Framework
Spring имеет встроенную поддержку event listeners:
// Определяем событие
public class UserRegisteredEvent extends ApplicationEvent {
private final String email;
public UserRegisteredEvent(Object source, String email) {
super(source);
this.email = email;
}
public String getEmail() {
return email;
}
}
// Издатель события
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void registerUser(String email) {
// Регистрируем пользователя
System.out.println("User registered: " + email);
// Публикуем событие
eventPublisher.publishEvent(new UserRegisteredEvent(this, email));
}
}
// Слушатель события
@Component
public class EmailNotificationListener {
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
System.out.println("Sending email to: " + event.getEmail());
// Логика отправки email
}
}
// Альтернатива с аннотацией
@Component
public class AnotherListener {
@EventListener(classes = UserRegisteredEvent.class)
public void handleUserRegistration(UserRegisteredEvent event) {
System.out.println("Notification: User " + event.getEmail() + " registered");
}
}
5. Weak Listeners (для предотвращения утечек памяти)
import java.lang.ref.WeakReference;
public class WeakListenerExample {
public interface DataChangedListener {
void onDataChanged(String data);
}
public class DataModel {
private List<WeakReference<DataChangedListener>> listeners = new ArrayList<>();
public void addWeakListener(DataChangedListener listener) {
listeners.add(new WeakReference<>(listener));
}
public void notifyListeners(String data) {
// Удаляем уже собранные слушатели
listeners.removeIf(ref -> ref.get() == null);
for (WeakReference<DataChangedListener> ref : listeners) {
DataChangedListener listener = ref.get();
if (listener != null) {
listener.onDataChanged(data);
}
}
}
}
}
6. Асинхронные Listeners
@Component
public class AsyncListenerExample {
@EventListener
@Async
public void onUserRegistered(UserRegisteredEvent event) {
// Выполняется в отдельном потоке
sendEmail(event.getEmail());
saveToDatabase(event.getEmail());
updateAnalytics(event.getEmail());
}
private void sendEmail(String email) {
System.out.println("Sending email to " + email);
}
private void saveToDatabase(String email) {
System.out.println("Saving to DB: " + email);
}
private void updateAnalytics(String email) {
System.out.println("Updating analytics for " + email);
}
}
7. Ordered Listeners (порядок выполнения)
@Component
@Order(1)
public class FirstListener {
@EventListener
public void onEvent(UserRegisteredEvent event) {
System.out.println("1st: Processing");
}
}
@Component
@Order(2)
public class SecondListener {
@EventListener
public void onEvent(UserRegisteredEvent event) {
System.out.println("2nd: Processing");
}
}
// Выполнятся в порядке: 1st → 2nd
8. Типичные типы Listeners (Java):
| Тип | Использование |
|---|---|
| ActionListener | Кнопки, меню |
| MouseListener | Клики мыши |
| KeyListener | Нажатия клавиш |
| WindowListener | События окна |
| ItemListener | Выбор в списках |
| DocumentListener | Изменения текста |
| ChangeListener | Изменение слайдера |
| FocusListener | Фокус компонента |
Преимущества Listeners:
✅ Слабая связь между компонентами
✅ Гибкость — легко добавлять/удалять слушателей
✅ Масштабируемость — один издатель может иметь много слушателей
✅ Асинхронность — обработка может быть неблокирующей
Когда использовать:
- UI события (клики, ввод)
- Уведомления об изменениях состояния
- Логирование и мониторинг
- Асинхронная обработка
- Event-driven архитектура
Listener — это один из самых важных паттернов в Java для создания отзывчивых приложений.