← Назад к вопросам

Что такое Listeners?

1.8 Middle🔥 61 комментариев
#SOLID и паттерны проектирования

Комментарии (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 для создания отзывчивых приложений.