Найти в Дзене
chto-to na itshnom

Всё о Java для начинающих чайников ч.2

Очередью в Java считается все, что наследует интерфейс Queue, который в свою очередь расширяет Collection. Это значит, что с очередями можно работать, как с коллекциями. Очереди в Java работают по двум принципам: FIFO и LIFO. FIFO — First In First Out, принцип обычной очереди (конечно, если нет тех кому нужно “только спросить”), в котором первый элемент попадает в очередь и первым выходит из нее. LIFO — Last In First Out, принцип стека, в котором последний элемент, добавленный в очередь, первым выйдет из нее. Например, как с колодой карт: ты будешь брать все карты с верха по одной, чтобы дойти до конца. Структура Здесь видно, что у Queue есть 3 класса реализации: LinkedList, ArrayDeque и PriorityQueue. LinkedList и ArrayDeque наследует напрямую не от Queue, а от Deque. основные методы Queue : Есть еще класс PriorityQueue, прямой наследник Queue: принцип его работы отличается от наследников Dequeue.
PriorityQueue — это очередь с приоритетом, которая по умолчанию размещает элементы со
Оглавление
  1. Очереди в Java, интерфейс Queue, PrioritiQueue. Структура, основные методы.

Очередью в Java считается все, что наследует интерфейс Queue, который в свою очередь расширяет Collection. Это значит, что с очередями можно работать, как с коллекциями.

Очереди в Java работают по двум принципам: FIFO и LIFO.

FIFO — First In First Out, принцип обычной очереди (конечно, если нет тех кому нужно “только спросить”), в котором первый элемент попадает в очередь и первым выходит из нее.

LIFO — Last In First Out, принцип стека, в котором последний элемент, добавленный в очередь, первым выйдет из нее. Например, как с колодой карт: ты будешь брать все карты с верха по одной, чтобы дойти до конца.

Структура

Здесь видно, что у Queue есть 3 класса реализации: LinkedList, ArrayDeque и PriorityQueue. LinkedList и ArrayDeque наследует напрямую не от Queue, а от Deque.

основные методы Queue :

  • add(E e). Добавляет указанный элемент в очередь, возвращая true в случае успеха и выдавая исключение IllegalStateException, если нет свободного места.
  • element(). Получает, но не удаляет верхний элемент очереди. Если очередь пуста, бросает исключение NoSuchElementException.
  • offer(E e). Вставляет указанный элемент в очередь, если это возможно сделать не нарушая ограничений пропускной способности.
  • peek(). Получает, но не удаляет верхний элемент очереди или возвращает null, если эта пуста.
  • poll(). Получает и удаляет верхний элемент очереди или возвращает null, если эта пуста.
  • remove(). Удаляет верхний элемент очереди. Если очередь пуста, бросает исключение NoSuchElementException.

Есть еще класс PriorityQueue, прямой наследник Queue: принцип его работы отличается от наследников Dequeue.

PriorityQueue — это очередь с приоритетом, которая по умолчанию размещает элементы согласно естественному порядку сортировки. Для сортировки здесь используется
Comparable и Comparator.

Основные методы класса PriorityQueue:

  • add(E e). Добавляет элемент в PriorityQueue.
  • clear(). Очищает PriorityQueue, удаляя все элементы.
  • comparator(). Возвращает пользовательский компаратор, используемый для упорядочивания элементов в очереди.
  • contains(Object o). Проверяет, присутствует ли данный элемент в PriorityQueue. Если да, возвращает true.
  • iterator(). Возвращает итератор для данного PriorityQueue.
  • offer(E e). Вставляет указанный элемент в PriorityQueue.
  • peek(). Используется для возврата заголовка очереди без удаления элемента.
  • poll(). Если очередь пуста, возвращает значение null, в противном случае удаляет и возвращает начало очереди.
  • size(). Возвращает количество элементов в PriorityQueue.
  1. Байтовые потоки InputStream и OutputStream. Консольный ввод и вывод Java. Символьные потоки данных. Абстрактные классы Writer, Reader.

В Java для работы с вводом-выводом данных используются байтовые и символьные потоки:

  • Байтовые потоки работают с данными в виде байтов. Они подходят для работы с бинарными файлами (например, изображения, видео).
  • Символьные потоки работают с данными в виде символов. Они используют кодировку и предназначены для работы с текстовыми файлами.

Классы InputStream и OutputStream - абстрактные классы, которые определяют базовые операции для чтения и записи байтов.

InputStream - это класс в Java, предоставляющий возможность чтения байтов из различных источников, таких как файлы или сетевые соединения.

InputStream is = new FileInputStream("input.txt");

int byteData = is.read(); // Возможность читать данные на уровне байтов

OutputStream - предназначен для записи байтов в разнообразные приемники, будь то файлы или сетевые сокетых.

OutputStream os = new FileOutputStream("output.txt");

os.write(65); // Записываем символ 'A' в виде байта

Основные методы:

• int read() – читает один байт.

• int read(byte[] b) – читает массив байтов.

• void write(int b) – записывает один байт.

• void write(byte[] b) – записывает массив байтов.

• void close() – закрывает поток.

В Java консольный ввод-вывод осуществляется с использованием:

  • System.in – стандартный ввод (InputStream).
  • Для получения ввода с консоли в классе System определен объект in. Однако непосредственно через объект System.in не очень удобно работать, поэтому, как правило, используют класс Scanner, который, в свою очередь использует System.in.
  • Класс BufferedReader позволяет читать строки или символы более эффективно (Он буферизует символы, чтобы можно было эффективно считывать символы, массивы и т. д. Он наследует класс чтения и делает код эффективным, поскольку мы можем считывать данные построчно с помощью метода readline()).
  • System.out – стандартный вывод (OutputStream).

Для вывода данных на консоль используется System.out. Это поток типа PrintStream, предоставляющий методы для вывода данных.

Основные методы:

• print(...) — вывод без переноса строки.

• println(...) — вывод с переносом строки.

• printf(String format, Object... args) — форматированный вывод.

Абстрактные классы Reader и Writer являются символьными потоками:

Reader: обеспечивает поддержку символьного потока чтения аналогично тому, как это делает InputStream, реализующий модель байтового потока ввода. Методы Reader схожи с теми, которые объявлены в составе InputStream.

Writer: обеспечивает поддержку символьного потока записи аналогично тому, как это делает OutputStream, реализующий модель байтового потока вывода. Многие методы Writer схожи с теми, которые объявлены в OutputStream; помимо этого, в классе Writer предусмотрены некоторые другие полезные версии метода write.

  1. Чтение и запись файлов. Классы FileInputStream, FileOutputStream. Файловый ввод-вывод с использованием символьных потоков. Классы FileReader и FileWriter.

Чтение и запись файлов в Java реализуется с использованием классов ввода-вывода (I/O).

Основные классы для работы с файлами:

  1. FileInputStream и FileOutputStream — используются для побайтового чтения и записи.
  2. FileReader и FileWriter — используются для символьного ввода-вывода.

Первые классы работают с потоками байтов, они являются наследниками абстрактных классов InputStream & OutputStream, которые являются суперклассами для реализаций чтения и записи в файлы.

FileInputStream и FileOutputStream подходят для работы с файлами, содержащими данные в бинарном формате, например, изображениями, аудио или видео (для текста тоже можно).

В конструкторе они принимают либо путь к целевому файлу, либо объект класса File.

-2
-3

Хотя с помощью ранее рассмотренных классов можно записывать текст в файлы, однако они предназначены прежде всего для работы с бинарными потоками данных, и их возможностей для полноценной работы с текстовыми файлами недостаточно. И для этой цели служат совсем другие классы, которые являются наследниками абстрактных классов Reader и Writer.

Классы FileReader и FileWriter работают с символьными потоками. Они служат для работы с текстовыми файлами, обеспечивая поддержку работы с символами и кодировками.

В конструктор передается либо путь к файлу в виде строки, либо объект File, который ссылается на конкретный текстовый файл. Параметр append указывает, должны ли данные дозаписываться в конец файла

-4
-5
  1. Многопоточное программирование: общие принципы.

Поток — это независимая последовательность выполнения, которая может выполняться параллельно с другими потоками. Каждый поток имеет свой собственный стек, регистры и локальные переменные, но может разделять память с другими потоками.

Выполнение нескольких потоков в рамках одного процесса или приложения.

Каждый поток имеет собственный счётчик программ, стек и локальные данные, но разделяет пространство памяти, глобальные данные и системные ресурсы с другими потоками в том же процессе.

• Параллельное выполнение задач. Например, один поток может обрабатывать данные, в то время как другой выводит информацию на экран. Эти действия независимы друг от друга и могут выполняться параллельно

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

• Синхронизация потоков. Она нужна, чтобы избежать конфликтов при доступе к общим ресурсам. Для этого используются механизмы синхронизации, такие как мьютексы и семафоры.

Java предоставляет класс Thread для управления потоками, который позволяет:

  • Запускать поток: start()
  • Приостанавливать поток: sleep(milliseconds)
  • Ожидать завершения потока: join()
  • Проверять состояние потока: isAlive()
  1. Класс Thread и интерфейс Runnable: создание потоков, приоритеты потоков.

https://java-online.ru/java-thread.xhtml

В Java для работы с потоками используются класс Thread и интерфейс Runnable, которые позволяют выполнять несколько задач одновременно (многопоточность).

Создание потоков:

1. Наследование от класса Thread

Класс Thread представляет собой поток выполнения. Для создания потока можно унаследоваться от этого класса и переопределить его метод run(), в котором описывается логика выполнения:

class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running...");
}
}

public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // запуск потока
}
}

Важно: Метод start() вызывает системный код, который запускает поток и вызывает его метод run(). Если вызвать run() напрямую, код выполнится в основном потоке, а не в новом.

2. Реализация интерфейса Runnable

Интерфейс Runnable позволяет создавать потоки без наследования от класса Thread. Это особенно полезно, если класс уже наследуется от другого класса:

class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread is running...");
}
}

public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start(); // запуск потока
}
}

Отличие: Наследование от Thread жестко связывает логику потока с классом, тогда как использование Runnable позволяет отделить поток выполнения от его логики. Кроме того, Java не поддерживает множественное наследование, поэтому Runnable гибче.

Приоритеты потоков

У каждого потока в Java есть приоритет, который влияет на порядок его выполнения. Приоритеты задаются числом от 1 до 10, где:

  • Thread.MIN_PRIORITY = 1 (минимальный приоритет),
  • Thread.NORM_PRIORITY = 5 (нормальный приоритет, значение по умолчанию),
  • Thread.MAX_PRIORITY = 10 (максимальный приоритет).

Пример установки приоритета:

Thread thread = new Thread(() -> System.out.println("Thread is running..."));

thread.setPriority(Thread.MAX_PRIORITY); // Устанавливаем максимальный приоритет

thread.start();

Особенности:

  • Поток с более высоким приоритетом имеет больше шансов получить процессорное время.
  • Приоритеты потоков зависят от реализации JVM (Java Virtual Machine) и операционной системы, поэтому их влияние не гарантируется.

Основные методы класса Thread:

1) start() — запускает поток. Вызывает метод run() в новом потоке.
2) run() — содержит код, который выполняется в потоке.
3) sleep(long millis) — приостанавливает выполнение потока на указанное время (в миллисекундах).
4) join() — заставляет текущий поток дождаться завершения другого.
5) setPriority(int priority) — задает приоритет потока.
6) isAlive() — проверяет, выполняется ли поток в данный момент.

  1. Приостановка и прерывание потоков. Определение момента завершения потока.

Приостановка потока

В современном Java не рекомендуется использовать устаревшие методы вроде suspend() и resume() (они были убраны из-за потенциальных проблем с безопасностью). Вместо этого для приостановки потока можно использовать метод сна (sleep()), механизм ожидания (wait()) или управляющий флаг.

Использование метода сна:

  • Поток засыпает на заданное время, освобождая процессор. Thread.sleep(1000); // Поток "уснет" на 1 секунду

Использование механизма ожидания:

  • Методы wait() и notify() - поток "ждет", пока другой поток или событие снимет блокировку.

Флаги или сигналы:

  • Программист может самостоятельно реализовать логику приостановки, например, с помощью переменных-флагов.
  • Поток проверяет значение флага и "останавливается", если это необходимо.

Прерывание потоков

Прерывание используется для сигнализации потоку о том, что он должен завершить свою работу. Метод interrupt() не останавливает поток немедленно, а подаёт сигнал (выставляет флаг прерывания), что поток должен остановиться. Поток может обработать этот сигнал и завершить работу.

Как работает interrupt():

  • Если поток находится в состоянии ожидания или сна (sleep(), wait()), он выбрасывает исключение InterruptedException.
  • Если поток не находится в этих состояниях, флаг прерывания будет установлен, и проверяется с помощью метода Thread.currentThread().isInterrupted().

Определение завершения потока

Чтобы определить, завершился ли поток, используется метод isAlive() или можно дождаться его завершения с помощью join().

Что делает join():

  • Ожидает завершения потока, прежде чем продолжить выполнение кода в основном потоке.
  • Можно передать таймаут, чтобы ждать ограниченное время: thread.join(3000).
  1. Синхронизация потоков.

Синхронизация потоков - это настройка взаимодействия потоков между собой. Несколько потоков могут активно работать, например, с одним и тем же набором данных и что-то в нем менять. Это создает проблемы.

Представь, что несколько потоков записывают текст в одно и то же место — например, в текстовый файл или консоль.

Этот файл или консоль в данном случае становится общим ресурсом. Потоки не знают о существовании друг друга, поэтому просто записывают все, что успеют за то время, которое планировщик потоков им выделит. Получается неразборчивый текст.

Поэтому в многопоточном программировании ввели специальное понятие мьютекс (от англ. «mutex», «mutual exclusion» — «взаимное исключение»).

Задача мьютекса — обеспечить такой механизм, чтобы доступ к объекту в определенное время был только у одного потока. Если Поток-1 захватил мьютекс объекта А, остальные потоки не получат к нему доступ, чтобы что-то в нем менять. До тех пор, пока мьютекс объекта А не освободится, остальные потоки будут вынуждены ждать.

В Java синхронизация реализуется с помощью ключевого слова synchronized, которое может быть применено:

  • К методам.
  • К блокам кода.

public synchronized void doSomething() {

}

public class Main {

private Object obj = new Object();

public void doSomething() {

synchronized (obj) {

}

}

}

Если один поток зашел внутрь блока кода, который помечен словом synchronized, он моментально захватывает мьютекс объекта, и все другие потоки, которые попытаются зайти в этот же блок или метод вынуждены ждать, пока предыдущий поток не завершит свою работу и не освободит монитор.

Эти два способа записи означают одно и то же:

public void swap() {

synchronized (this)

{

}

}

public synchronized void swap() {

}

}

  1. Архитектура JDBC (Java DataBase Connectivity). Двух и трехуровневые модели доступа к базе данных. Преимущества и недостатки JDBC.
  • Приложение: это Java-апплет или сервлет, который взаимодействует с источником данных.
  • Интерфейс JDBC: позволяет программам на Java выполнять SQL-запросы и получать результаты. Ключевые интерфейсы включают Driver, ResultSet, RowSet, PreparedStatement и Connection. Важные классы включают DriverManager, Types, Blob и Clob.
  • DriverManager: Он играет важную роль в архитектуре JDBC. Он использует некоторые драйверы для конкретных баз данных, чтобы эффективно подключать корпоративные приложения к базам данных.
  • Драйверы JDBC: эти драйверы обеспечивают взаимодействие между приложением и базой данных.

Архитектура JDBC состоит из двухуровневых и трехуровневых моделей обработки для доступа к базе данных.

Двухуровневая модель доступа:

Приложение Java напрямую взаимодействует с базой данных с помощью драйвера JDBC. Запросы отправляются в базу данных, а результаты возвращаются непосредственно в приложение. В клиент-серверной архитектуре компьютер пользователя (клиент) взаимодействует с удалённым сервером базы данных.

Клиентское приложение (Java) -> Драйвер JDBC -> База данных

Трехуровневая модель доступа:

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

Клиентское приложение -> Сервер приложений -> Драйвер JDBC -> База данных

Преимущества

  • Независимость от платформы: Позволяет работать с базой данных на разных платформах.
  • Стандартный API: Предоставляет единый интерфейс для различных баз данных.
  • Поддержка различных баз данных через драйверы
  • Расширяемость: предлагает такие функции, как пакетная обработка, объединение соединений и управление транзакциями.

Недостатки

  • Много ручного кода для работы с соединениями и запросами.
  • Сложность обработки ошибок и управление ресурсами.
  • Необходимость явного написания SQL-запросов, что снижает переносимость.
  • Ограниченная производительность при высоких нагрузках без оптимизаций.
  1. Библиотека Swing, общие черты и особенности.

Swing — это библиотека для создания графического пользовательского интерфейса (GUI) на языке Java. Она является частью Java Foundation Classes (JFC) и предоставляет мощный и гибкий инструментарий для создания приложений с современным дизайном и функциональностью. Swing работает поверх более базовой библиотеки AWT (Abstract Window Toolkit), предлагая расширенные возможности и независимость от платформы.

Общие черты

  • Кросс-платформенность: Swing-компоненты написаны на Java, благодаря чему приложения выглядят и работают одинаково на любых операционных системах, поддерживающих JVM.
  • Широкий набор компонентов: Swing предоставляет множество стандартных компонентов, таких как кнопки (JButton), текстовые поля (JTextField), таблицы (JTable), деревья (JTree) и вкладки (JTabbedPane), что позволяет создавать как простые, так и сложные пользовательские интерфейсы.
  • Модель MVC: Архитектура Swing основана на принципе «Модель-Вид-Контроллер» (MVC), что обеспечивает разделение логики данных, их отображения и управления, упрощая разработку и поддержку кода.
  • Поддержка событий: Swing реализует мощную модель событий, позволяющую отслеживать действия пользователя, такие как нажатия кнопок, ввод текста, перемещения мыши и другие взаимодействия с интерфейсом.
  • Гибкость и настраиваемость: Компоненты Swing легко кастомизируются, что позволяет разработчикам изменять их внешний вид, поведение и стили, а также добавлять собственные реализации.

Особенности:

  • Легковесные компоненты: Компоненты Swing являются легковесными, так как не зависят напрямую от графической системы операционной системы, а полностью реализованы средствами Java.
  • Двойная буферизация: Swing использует двойную буферизацию для рендеринга графики, что исключает мерцание и делает интерфейс более плавным.
  • Многоуровневая архитектура компоновки: Swing поддерживает вложенные панели и менеджеры компоновки (FlowLayout, BorderLayout, GridLayout), позволяя создавать сложные и гибкие графические интерфейсы.
  • Look and Feel: Swing предоставляет возможность изменять стиль и внешний вид компонентов, используя предустановленные стили (Metal, Nimbus, Windows, и другие) или создавая собственные.
  • Поддержка графики и анимации: Swing позволяет рисовать собственные компоненты и обрабатывать графику, обеспечивая поддержку сложных пользовательских элементов и анимации.
  • Поддержка сложных интерфейсов: Swing предоставляет компоненты для работы с табличными данными (JTable), иерархическими структурами (JTree), вкладками (JTabbedPane) и другими сложными элементами интерфейса.
  1. Виды контейнеров в Swing.

1. JFrame

JFrame — это основной контейнер для создания оконных приложений. Он представляет собой главное окно приложения и может содержать другие компоненты, такие как панели, кнопки и текстовые поля. JFrame может быть настроен для отображения заголовка, меню и других элементов интерфейса.

Пример создания JFrame:

-6

2. JPanel

JPanel — это универсальный контейнер, который может содержать другие компоненты. Он часто используется для группировки компонентов и управления их расположением. JPanel может использовать различные менеджеры компоновки для определения расположения своих дочерних компонентов.

Пример использования JPanel:

-7

3. JScrollPane

JScrollPane — это контейнер, который добавляет возможность прокрутки к другим компонентам, таким как JPanel или JTextArea. Он автоматически добавляет полосы прокрутки, если содержимое превышает размеры видимой области.

Пример использования JScrollPane:

-8

4. JTabbedPane

JTabbedPane — это контейнер, который позволяет организовать компоненты в виде вкладок. Каждая вкладка может содержать разные компоненты, и пользователь может переключаться между ними.

Пример использования JTabbedPane:

-9

5. JToolBar

JToolBar — это контейнер, который используется для размещения кнопок инструментов и других элементов управления. Он обычно располагается в верхней части окна и предоставляет быстрый доступ к часто используемым функциям.

Пример использования JToolBar:

-10

6. JLayeredPane

JLayeredPane — это контейнер, который позволяет размещать компоненты на разных уровнях (слоях). Это полезно для создания сложных интерфейсов, где компоненты могут перекрывать друг друга.

Пример использования JLayeredPane:

-11

7. JSplitPane

JSplitPane — это контейнер, который позволяет разделить область на две части, которые могут быть изменены по размеру. Это полезно для создания интерфейсов с изменяемыми панелями.

Пример использования JSplitPane:

-12
  1. Элементы пользовательского интерфейса Swing.

Категория

Компоненты

Пример кода

Основные контейнеры

JFrame – главное окно приложения

JDialog – диалоговое окно

JWindow – окно без рамки

java JFrame frame = new JFrame("Пример JFrame"); frame.setSize(400, 300); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);

Контейнеры для компоновки

JPanel – панель для группировки компонентов JScrollPane – панель с прокруткой

JTabbedPane – вкладки для отображения панелей

java JPanel panel = new JPanel(); panel.add(new JButton("Кнопка")); frame.add(panel);

Элементы управления

JButton – кнопка

JTextField – однострочное текстовое поле

JTextArea – многострочное текстовое поле

JComboBox – выпадающий список

java JButton button = new JButton("Нажми меня"); button.addActionListener(e -> JOptionPane.showMessageDialog(null, "Кнопка нажата!")); frame.add(button);

Элементы отображения

JLabel – текст/изображение

JProgressBar – индикатор выполнения

JToolTip – всплывающая подсказка

java JLabel label = new JLabel("Привет, Swing!"); frame.add(label);

Меню и панели инструментов

JMenuBar – главное меню

JToolBar – панель инструментов

java JMenuBar menuBar = new JMenuBar(); JMenu menu = new JMenu("Файл"); menu.add(new JMenuItem("Открыть")); menuBar.add(menu); frame.setJMenuBar(menuBar);

Диалоговые окна

JOptionPane – диалоговое окно с сообщением

JFileChooser – диалог для выбора файлов

JColorChooser – диалог для выбора цвета

java JOptionPane.showMessageDialog(null, "Это сообщение!");

Таблицы

JTable – таблица данных

java String[][] data = {{"1", "Иван"}, {"2", "Мария"}}; String[] columns = {"ID", "Имя"}; JTable table = new JTable(data, columns); frame.add(new JScrollPane(table));

Менеджеры компоновки

FlowLayout – слева направо

BorderLayout – 5 зон (NORTH, SOUTH и т. д.)

GridLayout – таблица

BoxLayout – вертикальное/горизонтальное выравнивание

java frame.setLayout(new FlowLayout()); frame.add(new JButton("Кнопка 1")); frame.add(new JButton("Кнопка 2"));

  1. Модель событий Swing. Интерфейс EventListener.

Модель событий Swing в Java основана на концепции делегирования обработки событий (event delegation model). Это означает, что источник события (например, кнопка или другой графический компонент) генерирует событие, а обработка события делегируется одному или нескольким слушателям.

Основные аспекты модели событий

  1. Источник событий (Event Source)
    Источником событий является компонент, который генерирует события, такие как щелчки мыши, нажатия клавиш или действия пользователя. Примеры: кнопки (JButton), текстовые поля (JTextField), окна (JFrame).
  2. События (Event Object)
    Событие — это объект, который содержит информацию о том, что произошло. В Java класс события наследуется от java.util.EventObject. В Swing используются такие подклассы, как:
  • ActionEvent — для событий действий (например, нажатие кнопки).
  • MouseEvent — для событий мыши.
  • KeyEvent — для событий клавиатуры.
  • WindowEvent — для событий окна.
  1. Слушатель событий (Event Listener)
    Интерфейсы, которые реализуются для обработки определённого типа событий. Каждый слушатель определяет один или несколько методов для обработки событий. Например:
  • ActionListener — интерфейс для обработки событий действия (ActionEvent).
  • MouseListener — интерфейс для обработки событий мыши.
  • KeyListener — интерфейс для обработки событий клавиатуры.
  1. Регистрация слушателей (Listener Registration)
    Для того чтобы слушатель мог обрабатывать события от источника, его нужно зарегистрировать через метод addXXXListener. Например:
  • addActionListener(ActionListener l) — для событий действия.
  • addMouseListener(MouseListener l) — для событий мыши.

Интерфейс EventListener

EventListener — это маркерный интерфейс (без методов), который лежит в основе всех слушателей событий в Java. Все интерфейсы слушателей (например, ActionListener, MouseListener) расширяют этот интерфейс.

Ключевые моменты

  1. Обработчик событий — это класс, который реализует интерфейс слушателя.
  2. Один источник события может иметь несколько слушателей.
  3. Модель событий Swing инкапсулирует сложность обработки пользовательского ввода.

Не уверен, что это нужно, но мало ли

-13
  1. Менеджеры компоновки Swing.

В Swing менеджеры компоновки (layout managers) используются для управления расположением компонентов внутри контейнеров. Каждый контейнер в Swing (например, JPanel, JFrame) имеет свой менеджер компоновки, который определяет, как размещать и изменять размеры компонентов.

Основные менеджеры компоновки

  • Полярное расположение BorderLayout: Разделяет контейнер на 5 зон - North, South, East, West и Center. Каждая зона может содержать только один компонент.
  • Последовательное расположение FlowLayout: Располагает компоненты в одну строку, перенося их на следующую строку, если не хватает места.
  • Табличное расположение GridLayout: Разбивает контейнер на сетку с фиксированным числом строк и столбцов. Все ячейки имеют одинаковый размер.
  • Менеджер расположения GridBagLayout: Один из самых гибких, но сложных менеджеров компоновки. Позволяет точно задавать размер и расположение компонентов, используя сетку с ячейками разного размера.
  • Менеджер расположения CardLayout: Позволяет переключаться между “карточками” (различными наборами компонентов).
  • Менеджер расположения BoxLayout: Располагает компоненты в одну строку (по горизонтали) или в один столбец (по вертикали).

Поддержка менеджеров расположения встроена в базовый класс контейнеров java.awt.Container. Все компоненты библиотеки Swing унаследованы от базового класса JComponent, который, в свою очередь, унаследован от класса Container. Таким образом, для любого компонента Swing можно установить менеджер расположения или узнать, какой менеджер им используется в данный момент. Для этого предназначены методы setLayout() и getLayout().

Управлять расположением компонентов желательно с помощью тех инструментов, которые специально для этого служат. Самый распространённый из них это — JPanel, мы не раз его использовали. Также следует помнить, что в виду изменения содержимого одного из компонентов, ему может перестать хватать прежних размеров. Или, наоборот, прежний размер для них будет чрезмерно велик. Проверку корректности габаритов для каждого компонента позволяет выполнить метод revalidate().

  1. GUI Designer Swing

GUI Designer Swing – это инструмент для разработки графических пользовательских интерфейсов (GUI) на платформе Java с использованием библиотеки Swing. Этот инструмент упрощает процесс создания интерфейсов и минимизирует объем ручного кода, который необходимо написать.

Основные особенности:

  • Вы видите интерфейс таким, каким он будет в реальном приложении, уже на этапе проектирования.
  • GUI Designer предоставляет удобный способ работы с менеджерами компоновки (Layout Managers), такими как:
  • GridBagLayout
  • BorderLayout
  • FlowLayout
  • BoxLayout и другие.
  • Позволяет перетаскивать визуальные компоненты (кнопки, поля ввода, панели, метки и т. д.) из панели инструментов на рабочую область.
  • После создания интерфейса в дизайнере автоматически генерируется код Java, который можно использовать в вашем проекте.
  • Часто используется в интегрированных средах разработки (например, IntelliJ IDEA или NetBeans).
  • Легко добавляются слушатели событий (ActionListener, MouseListener и т. д.) для обработки пользовательских действий.

Пример:

Допустим, вы используете GUI Designer в IntelliJ IDEA:

  1. Вы создаете новую форму (.form) и добавляете на нее элементы интерфейса.
  2. Среда автоматически генерирует код, например:

private JPanel mainPanel;

private JButton buttonOK;

private JTextField textField;

public MyForm() {

buttonOK.addActionListener(e -> JOptionPane.showMessageDialog(null, "Нажата кнопка!"));

}

public static void main(String[] args) {

JFrame frame = new JFrame("MyForm");

frame.setContentPane(new MyForm().mainPanel);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.pack();

frame.setVisible(true);

}

  1. Текстовые поля в Swing

Swing в Java — это инструментарий с графическим интерфейсом, который имеет широкий спектр виджетов для создания оптимизированных оконных приложений.

Текстовое поле в Swing— это компонент графического интерфейса, который позволяет пользователям вводить текст. Для создания и управления текстовыми полями в Swing используется класс JTextField (однострочный текст).

Для создания текстового поля чаще всего используются конструкторы:

· JTextField(int columns) — создаёт пустое текстовое поле, ширина которого достаточна для размещения columns символов. При этом пользователь может вводить в текстовое поле строку какой угодно длины: она просто будет прокручиваться.

· JTextField(String text) — создаёт текстовое поле с начальным текстом text.

· JTextField(String text, int columns) — устанавливает и ширину, и начальный текст.

Некоторые методы класса JTextField для работы с текстовыми полями:

· setText(String text) — устанавливает текст, отображаемый в текстовом поле, на указанное значение.

· getText() — возвращает текущий текст, введённый пользователем в текстовом поле.

· setColumns(int columns) — устанавливает предпочитаемое количество столбцов (ширину) текстового поля.

· addActionListener(ActionListener listener) — добавляет к текстовому полю ActionListener. Слушатель будет уведомлён, когда пользователь нажмёт клавишу «Enter», часто сигнализирующую об окончании ввода пользователя.

Текстовое поле JPasswordField, унаследованное от поля JTextField, дает возможность организовать ввод «закрытой» информации (чаще всего паролей), которая не должна напрямую отображаться на экране.

Существует также многострочное текстовое поле JTextArea. Оно предназначено для ввода простого неразмеченного различными атрибутами текста. В отличие от обычных полей, позволяющих вводить только одну строку текста, многострочные поля дают пользователю возможность вводить произвольное количество строк текста.

Для многострочных полей необходимо задавать не только ширину (максимальное количество символов), но и высоту (максимальное количество строк).

  1. Компонент управления JButton в Swing

JButton — это класс в библиотеке Swing, который представляет кнопку для пользовательского интерфейса. Она используется для выполнения определенного действия при нажатии.

Создание JButton

Для создания кнопки используется ее конструктор. Можно задать текст, иконку или оставить кнопку пустой:

JButton button = new JButton("Нажми меня"); // Кнопка с текстом
frame.add(button);

Обработка событий

Чтобы обработать нажатие кнопки, используется интерфейс ActionListener. Он позволяет выполнить код при нажатии:

button.addActionListener(e -> System.out.println("Кнопка нажата!"));

Пример:

JButton button = new JButton("Нажми меня");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "Кнопка была нажата!");
}
});

frame.add(button)

Основные методы JButton

1) Установка текста и иконки:

button.setText("Новый текст");
button.setIcon(new ImageIcon("path/to/icon.png"));

2) Изменение состояния:

setEnabled(boolean enabled) — включить/выключить кнопку.
isEnabled() — проверяет, активна ли кнопка.

3) Изменение цвета и шрифта:

button.setBackground(Color.BLUE);
button.setForeground(Color.WHITE);
button.setFont(new Font("Arial", Font.BOLD, 14));

Особенности и преимущества JButton

1) Гибкость: можно настроить текст, цвет, иконку и поведение кнопки.
2) Поддержка событий: легко обработать действия с помощью ActionListener.
3) Доступные состояния: кнопка может быть включена, выключена или скрыта.

  1. Платформа JavaFX, особенности, компоненты

JavaFX — это современная библиотека для создания графических пользовательских интерфейсов (GUI) в Java. Она была разработана как замена устаревшей библиотеки Swing. JavaFX предоставляет мощные инструменты для разработки настольных, мобильных и веб-приложений.

Особенности JavaFX

  • Кроссплатформенность: JavaFX поддерживает работу на всех основных операционных системах (Windows, macOS, Linux)
  • Гибкая разметка интерфейсов: Поддерживает CSS для стилизации компонентов. Использует FXML — XML-нотацию для описания интерфейсов.
  • Интеграция с современными технологиями: Легко связывается с базами данных, REST API и веб-сервисами. Поддержка видеоконтента (через Media и MediaView). Поддержка 3D-графики.
  • Поддержка MVC (Model-View-Controller): Легко реализовать архитектурный подход MVC для четкого разделения логики, данных и представления.

Основные компоненты JavaFX

Структура приложения: Приложение начинается с класса, наследующего javafx.application.Application. Основной метод start(Stage primaryStage) определяет главный интерфейс.

Stage: Представляет "главное окно" приложения. В каждом JavaFX-приложении есть хотя бы один объект Stage.(import javafx.stage.Stage;)

Scene: Scene отображает содержание сцены (stage). Каждая компонента stage может содержать несколько компонент scene, которые можно переключать. (import javafx.scene.Scene;)

Node: Каждая компонента stage может содержать различные компоненты, называемые узлами (node). Узлы могут быть элементами управления, такими как кнопки или метки, или даже макетами иногда их называют контейнерами (layout), которые могут содержать несколько вложенных компонентов. Каждая сцена (scene) может иметь один вложенный узел (node), но это может быть макет (layout), который может содержать несколько компонентов. Вложенность может быть многоуровневой — макеты могут содержать другие макеты и обычные компоненты.

Визуализация иерархии:
Scene: Scene отображает содержание сцены (stage). Каждая компонента stage может содержать несколько компонент scene, которые можно переключать. (import javafx.scene.Scene;) Node: Каждая компонента stage может содержать различные компоненты, называемые узлами (node). Узлы могут быть элементами управления, такими как кнопки или метки, или даже макетами иногда их называют контейнерами (layout), которые могут содержать несколько вложенных компонентов. Каждая сцена (scene) может иметь один вложенный узел (node), но это может быть макет (layout), который может содержать несколько компонентов. Вложенность может быть многоуровневой — макеты могут содержать другие макеты и обычные компоненты. Визуализация иерархии:
  1. Шаблон MVC (Model-View-Controller) в Spring.

MVC (Model–View–Controller) – это архитектурно/проектный шаблон, разделяющий приложение по трем основным логическим компонентам: контроллер, модель и представление.

Контроллер — это компонент, позволяющий соединять представления и модель, следовательно, он выступает в качестве посредника. Он отвечает за всю бизнес–логику и входящие запросы – получение информации от пользователя и ее интерпретация, обработка данных и обновление модели на основе действий пользователей и взаимодействие с View для получения конечного результата.

Модель – это компонент, позволяющий осуществить передачу данных, с которыми работает пользователь. Модель отвечает на запрос контроллера (так как контроллер самостоятельно не взаимодействует с базой), осуществляет различные операции с данными (CRUD – Create, Read, Update, Delete) и возвращает необходимые данные обратно.

Представление – задействовано в реализации всей логики пользовательского интерфейса приложения. Оно состоит из данных, которые собраны компонентами модели и передаются через контроллер.

  1. Классы StringBuffer и StringBuilder.

StringBuffer и StringBuilder — классы для работы со строками в Java, которые создают изменяемый набор символов.

  • StringBuffer

изменяемый и потокобезопасный благодаря синхронизации, но менее эффективный, чем StringBuilder, с точки зрения производительности. Лучше использовать в многопоточной среде.

  • StringBuilder

изменяемый, не потокобезопасный и более экономичный по сравнению со String. Лучше всего использовать для однопоточных операций.

Классы StringBuilder и StringBuffer предоставляют важные методы, которых не предоставляет класс String, такие как insert(), delete() и reverse().

  1. Архитектура JDBC (Java DataBase Connectivity). Двух и трехуровневые модели доступа к базе данных. Преимущества и недостатки JDBC.

JDBC (Java DataBase Connectivity) - интерфейс, который позволяет программистам соединяться с базой данных, запрашивать и обновлять данные с помощью языка структурированных запросов (SQL).

Архитектура JDBC состоит из двухуровневых и трехуровневых моделей обработки для доступа к базе данных.

Двухуровневая архитектура

Приложение Java взаимодействует напрямую с базой данных с помощью драйвера JDBC. Запросы отправляются в базу данных, а результаты возвращаются непосредственно приложению. При настройке клиент / сервер компьютер пользователя (клиент) взаимодействует с удаленным сервером базы данных.

Структура:

Клиентское приложение (Java) -> Драйвер JDBC -> База данных

Трехуровневая архитектура

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

Структура:

Клиентское приложение -> Сервер приложений -> Драйвер JDBC -> База данных

Преимущества JDBC

  • Прямой контроль и выполнение: JDBC позволяет разработчикам управлять SQL-запросами и оптимизировать их для конкретных задач.
  • Совместимость: JDBC поддерживает все основные СУБД, что обеспечивает универсальность.
  • Гибкость: Разработчики могут напрямую использовать SQL, что упрощает работу с нестандартными запросами.
  • Легкость интеграции: JDBC не требует дополнительных библиотек, что упрощает архитектуру приложения.

Недостатки JDBC:

  • Трудоемкость разработки: Работа с JDBC часто требует написания повторяющегося кода для управления соединениями, исключениями и обработкой данных.
  • Объектно-реляционное несоответствие: Преобразование данных между объектами Java и реляционными таблицами может быть сложным и затратным.
  • Отсутствие автоматизации: JDBC не предоставляет встроенных средств для работы с кэшем, транзакциями или пулом соединений — всё это необходимо реализовывать вручную.
  1. Массивы Java: объявление, инициализация. Основные методы класса Arrays. Доступ к элементам массивов, итерация массивов. Двумерные массивы.

Объявление и инициализация массивов

Объявление массива

Чтобы объявить массив в Java, необходимо указать тип элементов массива и использовать квадратные скобки. Пример:

1int[] numbers; // Объявление массива целых чисел

2String[] names; // Объявление массива строк

Инициализация массива

Инициализация массива может быть выполнена несколькими способами:

  • Инициализация с указанием размера:
  • 1int[] numbers = new int[5]; // Создание массива на 5 элементов
  • Инициализация с указанием значений:
  • 1int[] numbers = {1, 2, 3, 4, 5}; // Создание и инициализация массива
  • Инициализация с использованием оператора new:
  • 1String[] names = new String[]{"Alice", "Bob", "Charlie"}; // Создание и инициализация массива строк

Основные методы класса Arrays

Класс java.util.Arrays предоставляет множество статических методов для работы с массивами. Вот некоторые из них:

  • Arrays.sort(array): сортирует массив.
  • Arrays.copyOf(original, newLength): создает новый массив, копируя элементы из оригинального массива.
  • Arrays.equals(array1, array2): сравнивает два массива на равенство.
  • Arrays.toString(array): возвращает строковое представление массива.
  • Arrays.fill(array, value): заполняет массив указанным значением.

Доступ к элементам массивов

Доступ к элементам массива осуществляется с помощью индексов. Индексация начинается с нуля, то есть первый элемент имеет индекс 0, второй — 1 и так далее.

Итерация по массивам

Итерация по массивам может быть выполнена с использованием цикла for, for-each или while.

Цикл for:

1for (int i = 0; i < numbers.length; i++) {

2 System.out.println(numbers[i]);

3}

Цикл for-each:

1for (int number : numbers) {

2 System.out.println(number);

3}

Цикл while:

1int i = 0;

2while (i < numbers.length) {

3 System.out.println(numbers[i]);

4 i++;

5}

Двумерные массивы

Двумерные массивы представляют собой массив массивов. Они могут быть использованы для представления таблиц или матриц.

Объявление и инициализация двумерного массива

1int[][] matrix = new int[3][4]; // Создание двумерного массива 3x4

Или с инициализацией значений:

1int[][] matrix = {

2 {1, 2, 3, 4},

3 {5, 6, 7, 8},

4 {9, 10, 11, 12}

5};

Доступ к элементам двумерного массива

Доступ к элементам двумерного массива осуществляется с помощью двух индексов:

1int element = matrix[1][2]; // Доступ к элементу в строке 1 и столбце 2 (значение 7)

Итерация по двумерным массивам

Итерация по двумерным массивам может быть выполнена с использованием вложенных циклов:

1for (int i = 0; i < matrix.length; i++) {

2 for (int j = 0; j < matrix[i].length; j++) {

3 System.out.print(matrix[i][j] + " ");

4 }

5 System.out.println(); // Переход на новую строку после каждой строки матрицы

6}

  1. Иерархия наследования Java. Преобразование типов при наследовании. Ключевое слово instanceof.

Один класс наследует свойства и методы другого. Все классы наследуются от Object, если не указан другой родитель. Типы: одноуровневое, многоуровневое, интерфейсы, абстрактные классы.

java class Animal { void makeSound() { System.out.println("Звук"); } }

class Dog extends Animal { void bark() { System.out.println("Лай"); } }

Puppy p = new Puppy(); p.makeSound(); p.bark();

преобразование типов

Upcasting (восходящее преобразование): от подкласса к суперклассу, безопасно. Downcasting (нисходящее преобразование): от суперкласса к подклассу, требует явного приведения.

Оператор instanceof

Проверяет, принадлежит ли объект к классу или его подклассу. Используется для безопасного нисходящего приведения.

java Animal a = new Dog();

if (a instanceof Dog) { ((Dog) a).bark(); }

пример

java ArrayList<Animal> animals = new ArrayList<>();

animals.add(new Dog());

for (Animal a : animals) { if (a instanceof Dog) ((Dog) a).bark(); }

  1. Интерфейсы Java: определение интерфейса, реализация интерфейса. Преимущества применения интерфейсов. Переменные интерфейсов. Наследование интерфейсов. Методы по умолчанию. Статические методы интерфейсов.

Интерфейсы в Java — это абстрактные типы, которые определяют набор методов, но не предоставляют их реализацию. Они используются для обеспечения контракта, который обязуются выполнять классы, реализующие эти интерфейсы.

Реализация интерфейса

Класс, реализующий интерфейс, обязан предоставить реализацию всех его методов, если он сам не является абстрактным.

-15

Преимущества применения интерфейсов

Множественное наследование
Класс в Java может реализовывать несколько интерфейсов, что позволяет достичь множественного наследования, которого нет в наследовании классов.

Слабая связанность
Интерфейсы обеспечивают слабую связанность между классами, поскольку классы взаимодействуют через интерфейс, а не через конкретную реализацию.

Полиморфизм
Интерфейсы позволяют использовать один и тот же интерфейс для работы с различными объектами, что делает код гибким и масштабируемым.

Контракт на реализацию
Интерфейсы гарантируют, что все классы, их реализующие, будут иметь определённый набор методов.

Переменные интерфейсов

  • Все переменные интерфейсов:
  • Неизменяемые (final) — значение задаётся при объявлении.
  • Неявно public static final, то есть являются константами.
-16

Наследование интерфейсов

Интерфейсы могут наследоваться от других интерфейсов с использованием ключевого слова extends. Интерфейс может наследовать несколько других интерфейсов.

-17

Методы по умолчанию в интерфейсах

В Java 8 были добавлены методы по умолчанию (default methods), которые позволяют добавлять методы с реализацией в интерфейс, не нарушая совместимость с существующими классами.

-18

Статические методы интерфейсов

С версии Java 8 интерфейсы могут содержать статические методы. Эти методы не наследуются классами, а вызываются через имя интерфейса.

-19

Ключевые моменты

Абстракция: Интерфейсы позволяют определить контракт, не включая детали реализации.

Множественное наследование: Класс может реализовать несколько интерфейсов.

Методы по умолчанию: Предоставляют реализацию метода внутри интерфейса (начиная с Java 8).

Статические методы: Интерфейсы могут иметь методы, которые вызываются через имя интерфейса.

Константы: Все переменные интерфейса — это публичные, статические и финальные константы.

  1. Байтовые потоки InputStream и OutputStream. Консольный ввод и вывод Java. Символьные потоки данных. Абстрактные классы Writer, Reader. - это вопрос 28
  2. Основные фреймворки и задачи, решаемые Spring.

Spring для Java — обширная платформа для создания веб-проектов на Java, состоящая из множества независимых модулей (проектов) для разных задач: от простых веб-приложений до Big Data.

Spring состоит из большого числа модулей. Среди них есть модули-стартеры, без которых Spring-приложение просто не запустится, а есть также вспомогательные проекты, добавляющие в приложение определённую функциональность.

Spring Framework — ядро платформы Spring. Framework неявно используется другими компонентами Spring, обеспечивая фундаментальные инструменты для различных архитектур приложений.

Spring Framework включает(думаю можно не писать):

  • Основные технологии: внедрение зависимостей, события, ресурсы, i18n, проверка, связывание данных, преобразование типов, SpEL, AOP.
  • Инструменты тестирования: mock-объекты, TestContext, Spring MVC Test, WebTestClient.
  • Доступ к данным: транзакции, поддержка DAO, JDBC, ORM, Marshalling XML.
  • Интеграцию: удалённое взаимодействие, JMS, JCA, JMX, электронная почта, задачи, планирование, кеш.

Основные модули и фреймворки Spring:

  • Spring Boot — комплексный фреймворк для создания и запуска приложений с минимальными усилиями и настройками. Этот модуль делится на два стека: основанный на API сервлетов Spring MVC и реактивный Spring WebFlux.
  • Spring WebFlux — веб-платформа, созданная, чтобы по максимуму использовать преимущества современных многоядерных процессоров и обрабатывать огромное количество одновременных подключений.
  • Spring MVC построен на API сервлетов и использует архитектуру синхронного блокирующего ввода-вывода с моделью «один запрос на поток».

Характеристики

  1. Готовые стартовые зависимости, упрощающие конфигурацию сборки.
  2. Возможность сконфигурировать проект прямо в браузере с помощью Spring Initializr.
  3. Автоматическая настройка сторонних библиотек (по возможности).
  4. Готовые к работе функции, такие как сбор метрик, проверка работоспособности и использование внешней конфигурации.
  5. Нет кодогенерации и не требуется конфигурация XML — всё конфигурируется через аннотации.
  • Spring Data — модуль обеспечивает приложениям доступ к данным через реляционные и нереляционные базы данных (БД), map-reduce фреймворки и облачные сервисы. Spring Data содержит множество подпроектов, предназначенных для определённых СУБД.

Основной механизм, реализуемый в Spring Data — репозиторий. Это набор интерфейсов, использующих JPA Entity для взаимодействия с данными.

Характеристики

  1. Настраиваемое отображение сущностей в БД на Java-объекты.
  2. Создание динамических запросов в базу данных через сигнатуру метода интерфейса репозитория.
  3. Базовые классы для различных задач.
  4. Прозрачный аудит объектов.
  5. Возможность интегрировать собственный код репозитория.
  6. Простая интеграция со Spring через JavaConfig, а также кастомных пространств имён XML.
  7. Расширенная интеграция с контроллерами Spring MVC.
  • Spring Security — среда аутентификации, авторизации и контроля доступа. Это стандартный фреймворк, который используется для защиты приложений на основе Spring.

Spring Security предоставляет базовые функции безопасности, которые можно легко расширить для ваших собственных нужд.

Характеристики

  1. Аутентификация и авторизация пользователей.
  2. Защита от атак, таких как фиксация сессии, кликджекинг, подделка межсайтовых запросов и так далее.
  3. Возможность интеграции с Servlet API.
  4. Опционально подключаемый модуль Spring Web MVC.
  • Со Spring Cloud вы сможете легко и быстро создавать шаблоны в распределённых системах. Из примеров таких шаблонов: управление конфигурацией, обнаружение сервисов, интеллектуальная маршрутизация, микропрокси, одноразовые токены и многое другое.

Шаблоны, созданные с помощью Spring Cloud, будут хорошо работать в любой распределённой среде, включая ваш собственный ноутбук, центры обработки данных и PaaS-платформы, такие как Cloud Foundry.

Spring Cloud также состоит из множества подпроектов для разных целей. Так, Spring Cloud Azure интегрирует Spring со службами Azure, Spring Cloud Stream используется для создания управляемых событиями микросервисов (event-driven microservices) и так далее.

Характеристики

  1. Распределённая / версионная конфигурация.
  2. Регистрация и обнаружение сервисов.
  3. Маршрутизация.
  4. Связь между сервисами (service-to-service calls).
  5. Балансировка нагрузки.
  6. Выбор лидера и состояние кластера.
  7. Распределённый обмен сообщениями.
  • Spring Batch — платформа для разработки пакетных приложений. Spring Batch подойдёт как для простых, так и для более сложных проектов — платформа легко масштабируется и может обрабатывать большие объёмы информации.

Характеристики

  1. Управление транзакциями.
  2. Обработка на основе фрагментов данных.
  3. Декларативный ввод / вывод.
  4. Веб-интерфейс администрирования (Spring Cloud Data Flow).
  5. Spring Inversion of Control (IoC) контейнер Spring.

Spring предоставляет IoC-контейнер, который отвечает за управление жизненным циклом бинов (объектов, управляемых Spring). Базовый интерфейс для этого контейнера — BeanFactory. Однако в большинстве приложений используется ApplicationContext, который расширяет BeanFactory и предлагает дополнительные функции.

Ключевая особенность приложения, написанного на Spring, состоит в том что большую часть объектов создаем не мы, а Spring. Мы лишь конфигурируем классы (с помощью аннотаций либо в конфигурационном XML), чтобы «объяснить» фреймворку Spring, какие именно объекты он должен создать за нас, и полями каких объектов их сделать. Spring управляет созданием объектов и потому его контейнер называется IoC-контейнер. IoC расшифровывается как Inversion of Control. А объекты, которые создаются контейнером и находятся под его управлением, называются бинами.

Иллюстрировать это можно так:

-20

В общем на вход контейнер Spring принимает:

  • Наши обычные классы (которые впоследствии будут бинами).
  • Конфигурацию (неважно как именно ее задавать – либо в специальном файле XML, либо с помощью специальных аннотаций).

А на выходе он производит объекты – бины. То есть экземпляры классов, созданные в соответствии с конфигурацией и внедренные куда нужно (в другие бины). После этого никакие операторы new нам не понадобятся, мы будем работать в классе-бине с его полями-бинами так, будто они уже инициированы. Конечно, не со всеми полями, а только с теми, которые сконфигурированы как бины. Остальные инициализируются как обычно, в том числе с помощью оператора new.

  1. Dependency Injection (DI) в Spring.

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

Основные принципы DI:
1)
Инверсия управления: вместо создания объектов и управления их зависимостями вручную, Spring берет эту задачу на себя.
2)
Разделение ответственности: объекты только используют зависимости, но не создают их, что улучшает тестируемость и модульность кода.

Реализация DI в Spring

В Spring DI достигается через контейнер IoC, который управляет созданием, конфигурированием и связыванием объектов. Существует три способа внедрения зависимостей:

1) Внедрение через конструктор – Рекомендуемый подход для внедрения обязательных зависимостей.
Пример:

@Component
public class Service {
private final Repository repository;
public Service(Repository repository) { // Внедрение зависимости через конструктор
this.repository = repository;
}
public void doSomething() {
repository.save();
}
}

@Component
public class Repository {
public void save() {
System.out.println("Данные сохранены!");
}
}

Контейнер Spring автоматически создаст объект Repository и передаст его в Service.

2) Внедрение через сеттер – Используется для внедрения необязательных зависимостей.
Пример:

@Component
public class Service {
private Repository repository;
@Autowired
public void setRepository(Repository repository) { // Внедрение через сеттер
this.repository = repository;
}
public void doSomething() {
repository.save();
}
}

3) Внедрение через поле – Наиболее простой, но менее гибкий способ. Используется с аннотацией @Autowired.
Пример:

@Component
public class Service {
@Autowired
private Repository repository;
public void doSomething() {
repository.save();
}
}

Аннотации для DI в Spring

1) @Component — указывает, что класс является компонентом, управляемым Spring.
2)
@Autowired — автоматически внедряет зависимости (может использоваться на конструкторах, сеттерах или полях).
3)
@Qualifier — уточняет, какой именно компонент внедрять, если их несколько.
4)
@Primary — отмечает предпочтительный компонент, если их несколько.
5)
@Configuration и @Bean — используются для явного создания бинов.

Пример с явной конфигурацией:

@Configuration
public class AppConfig {
@Bean
public Repository repository() {return new Repository();}

@Bean
public Service service(Repository repository) {return new Service(repository);}

}

Преимущества Dependency Injection

1) Модульность: уменьшает связанность между классами.
2)
Тестируемость: упрощает создание юнит-тестов, позволяя легко использовать моки.
3)
Гибкость: позволяет менять зависимости без изменения кода.
4)
Упрощение кода: Spring берет на себя управление зависимостями.

  1. Жизненный цикл объекта Bean Spring.

Если кратко:

[Создание Bean] -> [Внедрение зависимостей] -> [Пост-обработка до инициализации] -> [Инициализация] -> [Пост-обработка после инициализации] -> [Использование Bean] -> [Уничтожение]

Создание Bean
Контейнер Spring создает экземпляр объекта Bean с помощью рефлексии на основании конфигурации (Java-код, XML или аннотации). На этом этапе не выполняется внедрение зависимостей.

Внедрение зависимостей (Dependency Injection)
Контейнер устанавливает значения свойств и передает зависимости через конструктор, сеттеры или поле (в случае аннотации @Autowired), а также через конфигурацию XML.

Пост-обработка Bean (Post-Processing)
На этом этапе контейнер вызывает метод postProcessBeforeInitialization у всех зарегистрированных бинов, которые реализуют интерфейс BeanPostProcessor. Это позволяет выполнять кастомную логику до инициализации Bean.

Инициализация Bean
После пост-обработки вызывается метод инициализации.

  • Если Bean реализует интерфейс InitializingBean, вызывается его метод afterPropertiesSet().
  • Если задан пользовательский метод инициализации (например, через аннотацию @Bean(initMethod = "init") или XML-атрибут init-method), он также будет вызван.

Пост-обработка после инициализации (Post-Initialization)
Контейнер вызывает метод postProcessAfterInitialization у всех бинов, реализующих BeanPostProcessor. Это позволяет модифицировать или обернуть Bean после его инициализации.

Использование Bean
После всех этапов инициализации Bean готов к использованию. На этом этапе объект выполняет свои бизнес-функции.

Завершение работы (Destroy)
Когда контейнер завершает свою работу, он уничтожает Bean:

  • Если Bean реализует интерфейс DisposableBean, вызывается метод destroy().
  • Если задан пользовательский метод уничтожения (через @Bean(destroyMethod = "cleanup") или XML-атрибут destroy-method), он также вызывается.
  1. Конфигурация ApplicationContext с помощью xml в Spring.

ApplicationContext — это главный интерфейс в Spring-приложении, который предоставляет информацию о конфигурации приложения.

Первый этап - чтение конфигураций и создание BeanDefinition.

BeanDefinition — это интерфейс, который описывает бин, его свойства, аргументы конструктора и другую метаинформацию.

Что касается конфигурации самих бинов, у Spring есть 4 способа конфигурации. Один из них - Xml конфигурация — ClassPathXmlApplicationContext(”context.xml”);

XML-конфигурация позволяет определить:

  1. Бины и их зависимости.
  2. Указание сканируемых пакетов для автоматической регистрации бинов.
  3. Настройку дополнительных модулей, таких как транзакции, AOP и другие.

Создаем XML-файл (например, applicationContext.xml):

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- Определение Engine -->

<bean id="engine" class="Engine">

<property name="type" value="V8" />

</bean>

<!-- Определение Car -->

<bean id="car" class="Car">

<property name="engine" ref="engine" />

</bean>

</beans>

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

Car car = context.getBean("car", Car.class);

car.start();

}

}

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

@Component public class Engine { public String getType() { return "V6"; } }

<!-- Сканирование пакета на наличие компонентов --> <context:component-scan base-package="com.example" />

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = context.getBean(Car.class);
car.start();

  1. Область видимости Bean в Spring.

Область видимости (scope) определяет, как и сколько раз бин создается и используется в рамках приложения.

Пример определения области:

класс определения бина:

-21

xml:

-22

Основные области видимости:

  • Singleton (по умолчанию)

контейнер создаёт один экземпляр этого компонента; все запросы к этому компоненту будут возвращать один и тот же объект, который кэшируется. Любые изменения объекта будут отражаться во всех ссылках на компонент.

Подходит для статичных, неизменяемых объектов, общих для приложения.

  • Prototype

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

  • Request

Новый бин создается для каждого HTTP-запроса.

Используется в веб-приложениях для работы с данными конкретного запроса.

  • Session

Новый бин создается для каждой HTTP-сессии.

Полезно для хранения пользовательских данных, которые должны сохраняться на протяжении сессии.

  • Global Session

Создаётся один экземпляр бина на каждую глобальную HTTP сессию.

  1. Фабричные или factory-методы в Spring.

Фабричный метод (Factory method) - это паттерн программирования. Данный паттерн позволяет создавать объекты не напрямую (использование оператора new), а через вызов специального (фабричного) метода, который после создания объекта передает его в качестве возвращаемого типа. Внутри данного метода всё равно создаются объекты при помощи оператора new, но это будет происходить уже внутри метода. Данная реализация удобна, когда необходимо перед использованием объекта произвести какие-либо настройки внутри объекта.

Преимущества использования фабричных методов

  • Инкапсуляция логики создания объектов : определиться с закрытием деталей создания объектов от клиента.
  • Гибкость : Легко под угрозой при создании различных объектов.
  • Расширяемость : Можно изменять способ создания объектов без изменения клиентского кода.
  • Поддержка шаблона Singleton : Фабричные методы упрощают контроль над созданием единственного экземпляра класса.
  • Поддержка инверсии управления (IoC) : В Spring фабричные методы интегрируются с контейнером IoC для управления бинарными файлами.

В Spring существует три типа фабричных методов:

  • Статический фабричный метод для шаблона Singleton

Этот метод используется для возврата единственного экземпляра собственного класса. Такой подход часто применяется для шаблона обеспечения Singleton, когда требуется иметь только один экземпляр класса во всем приложении.

  • Статический фабричный метод создания экземпляров другого класса

Данный метод используется для создания и возврата экземпляров другого класса. Он применяется, когда процесс создания объекта требует логики, обеспечивающей время выполнения программы.

  • Нестатический фабричный метод

Метод этого типа возникает в экземпляре класса и используется для возврата данных другого класса. Он позволяет сделать процесс создания более гибким и подстраиваемым в соответствии с конкретными требованиями.

  1. Конфигурация ApplicationContext с помощью аннотаций в Spring.

Основные аннотации для конфигурации ApplicationContext

  1. @Configuration: Эта аннотация указывает, что класс содержит определения бинов. Классы, помеченные этой аннотацией, могут содержать методы, аннотированные @Bean, которые возвращают экземпляры бинов.
  2. @Bean: Эта аннотация используется для определения бина в методе класса, помеченного @Configuration. Метод, аннотированный @Bean, должен возвращать объект, который будет управляться контейнером Spring.
  3. @Component: Эта аннотация используется для автоматического обнаружения и регистрации бинов. Классы, помеченные @Component, будут автоматически сканироваться и добавляться в контекст.
  4. @Autowired: Эта аннотация используется для автоматического внедрения зависимостей. Spring будет автоматически разрешать зависимости и внедрять необходимые бины.
  5. @ComponentScan: Эта аннотация указывает Spring, где искать компоненты для автоматического сканирования и регистрации.
  6. @Value: Эта аннотация используется для внедрения значений из конфигурационных файлов (например, application.properties).
  7. Связывание в Spring, аннотация @Autowired.

Связывание (Dependency Injection)

Механизм внедрения зависимостей, при котором Spring автоматически создает и управляет объектами, подставляя их в нужные места.

class Engine {}

class Car { private Engine engine; public Car(Engine engine) { this.engine = engine; } }

Аннотация @Autowired

Автоматически внедряет зависимости в поля, конструкторы или сеттеры. Работает с контейнером Spring, который управляет зависимостями.

@Component class Engine {}

@Component class Car { @Autowired private Engine engine; }

Способы внедрения зависимостей

1. Через конструктор (предпочтительный).

2. Через поле.

3. Через сеттер.

@Autowired public Car(Engine engine) { this.engine = engine; }

  1. Архитектурный стиль REST.

REST (Representational State Transfer) — это архитектурный стиль проектирования распределённых систем, особенно веб-сервисов. REST основывается на использовании стандартов веба (HTTP, URI и т. д.) для взаимодействия между клиентом и сервером

Принципы REST

Клиент-серверная архитектура: клиент и сервер разделены, взаимодействуют через API.

Отсутствие состояния (stateless): сервер не хранит информацию о состоянии клиента между запросами.

Кэшируемость: ответы могут кэшироваться для повышения производительности.

Единообразие интерфейса: работа с ресурсами через URI и методы HTTP.

Слои (layered system): сервер может иметь промежуточные слои (балансировщики, кэши).

Гипермедиа (HATEOAS): клиент получает ссылки на доступные действия в ответе.

Преимущества REST

  • Простота и понятность.
  • Масштабируемость и независимость клиента/сервера.
  • Поддержка кэширования.
  1. Spring Web-MVC, основная схема и логика работы.

Spring MVC — это веб-фреймворк Spring. Он позволяет создавать веб-сайты или RESTful сервисы (например, JSON/XML) и хорошо интегрируется в экосистему Spring, например, он поддерживает контроллеры и REST контроллеры в ваших Spring Boot приложениях.

Данный подход разделяет приложение на три основных компонента:

модель, представление и контроллер. Эти части взаимодействуют друг с

другом, но модификация каждого элемента может осуществляться

независимо.

  • Модель (Model) отвечает за работу с данными, включая их хранение, обработку и валидацию;
  • Контроллер (Controller) реализует логику обработки HTTP-запросов и использует стандартные методы REST для выполнения операций над ресурсами;
  • Представление (View) формирует данные, которые возвращаются клиенту.

Таким образом, обеспечивается динамическое взаимодействие между

пользователем и сервером, где данные проходят через все основные слои

приложения.

-23

Вся логика работы Spring MVC построена вокруг DispatcherServlet, который принимает и обрабатывает все HTTP-запросы (из UI) и ответы на них (последовательность событий, соответствующая входящему HTTP-запросу):

  1. После получения HTTP-запроса DispatcherServlet обращается к интерфейсу HandlerMapping, который определяет, какой Контроллер должен быть вызван, после чего, отправляет запрос в нужный Контроллер.
  2. Контроллер принимает запрос и вызывает соответствующий служебный метод, основанный на GET или POST. Вызванный метод определяет данные Модели, основанные на определённой бизнес-логике и возвращает в DispatcherServlet имя Вида (View).
  3. При помощи интерфейса ViewResolver DispatcherServlet определяет, какой Вид нужно использовать на основании полученного имени.
  4. После того, как Вид (View) создан, DispatcherServlet отправляет данные Модели в виде атрибутов в Вид, который в конечном итоге отображается в браузере.