Насколько насущный для людей уже имеющих какой-никакой опыт в Java вопрос о повышении уровня и движении дальше? Есть люди, которые выбирают долгий и тернистый путь Back-End разработчика штудируя все новые и новые для себя языки программирования, углубляясь в аппаратную или даже DevOps часть. Безусловно, это все полезные навыки и честь и хвала тому кто выбрал для себя этот путь. Но ведь есть и такие которые "всем сердцем любят" Java и хотят достичь высот именно с этим языком, не "отвлекаясь на всякие" Ruby-on-Rails, Python, C# или node.js.
При достижении определенного пика на уровне junior сложно понять, что именно надо знать и понимать для повышения своего скила. А ведь есть ряд вопросов которые, по моему мнению, являются базовыми, от которых уже можно "танцевать" и выстраивать логические цепочки в хитросплетениях этого богатого языка. Конечно это не отменяет того, что для повышения своего скила, а как следствие и уровня оплаты труда, полезно знать множество "сопроводительных" технологий, таких как ElasticSearch, Queue, AWS или GCS. Но это все специфика проекта на который вы собеседуетесь. А базовые знания для этого уровня, как ни странно, примерно одни. Это не значит что Вам можно "забить" на изучение других технологий и штудировать эти(либо подобные) вопросы - всю спецификацию проекта знать(или хотя бы понимать для чего и как используется та или иная технология) необходимо, однако знание базы на собеседовании даст вам необходимый плюс перед другими кандидатами.
И так, я бы выделил несколько тем которые следует знать, если не досконально, то хотя бы на достаточно высоком уровне: Java core, Java Collection Framework, Multithreading, OOP, SQL ну и конечно же Spring Framework. Каждая из этих тем встречается довольно часто и на собеседованиях на junior уровень, но для уровня middle нужны более углубленные знания. Там где junior скажет что в Java есть два типа памяти и каждая из них хранит свой тип данных, middle разработчик должен подробно объяснить структуру и принципы работы. В общем если junior должен знать что это такое, то middle уже должен еще и знать и понимать "с чем его едят". Естественно вопросы типа "Как перебрать все элементы HashMap?" должны вызывать у вас улыбку и незамедлительный и правильный ответ.
Java Core
Java Core обширная тема, разговаривая по которой можно уходить далеко в "дебри" языка. Вас, безусловно, будут спрашивать о Java Core на любом из собеседований, это база отталкиваясь от которой можно составить первое впечатление о собеседнике и выстроить процесс дальнейшего общения. Если Вы ответите на все вопросы связанные с Java Core, то и по другим темам самой Java вас будут спрашивать куда меньше. Ниже приведены примеры вопросов которые могут встретиться на собеседовании.
Какие бывают типы памяти в Java?
В Java существует два вида памяти - heap и stack. Каждый из них хранит свой вид данных, имеет свою структуру и работает по своей схеме. Heap выделяет память под объекты и JRE классы, stack в свою очередь хранит ссылки на объекты и примитивы.
В чем разница между heap и stack?
Heap используется всеми частями приложения, в то время как stack используется лишь главным потоком выполнения программы.
Каждый раз когда мы создаем объект(практически всегда используя ключевое слово new
) - этот объект хранится в heap, а в stack хранится ссылка на этот объект:
Person person = new Person();
тут мы создаем новый объект Person(), после чего он сразу же помещается в heap, а person становится ссылкой на этот объект и хранится в stack.
Stack - упорядоченная структура и работает по схеме LIFO(Last-In-First-Out). у heap весь доступ к объектам происходит по ссылкам из stack.
Heap в разы больше stack, stack работает быстрее благодаря структуре, stack "живет" короткий промежуток времени, в то время как heap "живет" весь "жизненный цикл" программы.
Какая структура у heap?
Heap имеет структуру пирамиды. Это означает что самый большой элемент всегда будет занимать самую высокую позицию. Иллюстрация приведена ниже на рисунке.
![Структура heap памяти. Структура heap памяти.](https://habrastorage.org/getpro/habr/upload_files/2ca/9b3/e0c/2ca9b3e0c5228d0e0ad45b766eb16f4e.webp)
Вставляемый новый узел помещается в конец пирамиды. Но согласно условия что дочерний узел не может быть больше родительского, идет проверка с родительским узлом. Если новый элемент меньше - операция вставки закончена, если нет - новый элемент меняется местами с родительским, до момента пока родительского узла не останется(либо родительский элемент не будет больше дочернего).
Благодаря своей пирамидной структуре(если угодно - структура бинарного дерева) вставка/удаление элемента происходит за время O(logN).
Что такое packege access level?
В Java существует 4 модификатора доступа: 3 из них явных и один неявный. Private/public/protected - явные модификаторы, это означает что каждый из них нужно объявлять в коде. Так же существует четвёртый модификатор доступа - packege access level. Его необязательно объявлять в коде, данный модификатор означает что поле/метод будут доступны на уровне пакета или наследникам данного класса.
Что означает понятие JIT?
Аббревиатура JIT означает Just-In-Time. В JRE существует подобный компилятор, который компилирует байт-код в собственный машинный код прямо во время выполнения программы. Таким образом повышается производительность Java-программ. В свою очередь JIT компилятор повышает непредсказуемость работы программы и повышает сложность отслеживания причины багов и ошибок. Так же такому компилятору необходимо гораздо больше памяти в сравнении с интерпретируемой компиляцией.
Для чего нужна Double Brace инициализация в Java?
Double Brace инициализация используется в Java для наполнения коллекций(set, list, map, queue) одновременно с их объявлением. В случае если вам необходимо создать unmodifiable коллекцию, без Double Brace инициализации нам будет необходимо создать список, положить туда необходимое кол-во элементов и создать из этого списка unmodifiableList используя Collections класс. Используя Double Brace инициализацию мы имеем возможность "положить" в unmodifiableList все необходимые элементы сразу при объявлении.
Что такое WeakReference и SoftReference в Java? Какая разница между этими понятиями?
WeakReference и SoftReference упоминается в контексте сборки мусора.
SoftReference используется при кешировании внутри системы и будет удален сборщиком мусора в случае если осталось мало памяти, а на объект существуют только ссылки SoftReference. Это критично при кэшировании, так как наш сборщик мусора самостоятельно освободит нам память в критичной ситуации, но до этого момента не будет "трогать" эти объекты.
WeakReference - в случае если на объект ссылаются только через weak-ссылки, то объект будет удален сразу при обходе сборщиком мусора.
Это критические отличия между этими двумя типами ссылок.
Для чего используют слово static в Java? Возможно ли переопределить статический метод?
Ключевым словом static
в Java можно пометить поле, метод, блок или внутренний класс и это будет означать что этот субъект принадлежит классу, а не объекту. Иными словами - при изменении субъекта, он одинаково изменится для всех объектов данного класса.
Мы можем перегрузить статический метод, но мы не можем его переопределить, так как он принадлежит классу.
Java Collection Framework
Так как Java язык для обработки большого количества данных, то и коллекции Вам знать просто необходимо! В целом, как правило, на этой теме внимания не заостряют, но Вы должны знать это и быть готовым вопросам сложнее чем просто "В чем разница между Set и List?" - это и так Вам должно быть известно и если Вам задали такой вопрос при собеседовании на должность middle, то стоит задуматься о квалификации того кто задал вопрос и о его компании в целом. Я выбрал несколько вопросов, которые помогут Вам более детально понять в каком направлении следует "копать".
В чем различия ArrayList и LinkedList?
В первую очередь в самой структуре - ArrayList "под коробкой" использует массив, следовательно, каждый раз при вставке элемента будет создаваться новый массив размера n+1(где n размер массива до вставки). Из-за этого для вставки элемента в середину списка потребуется сначала "освободить" место под новый элемент, "сдвинув" все элементы после места вставки влево. Вставка в конец массива происходит за константное время. Доступ же к элементам происходит быстрее благодаря индексу элемента.
В свою очередь в LinkedList каждый элемент "знает" своих соседей. Следовательно, что бы вставить новый элемент(удалить старый) в середину все что нам надо это записать ссылки на соседей и перезаписать у соседей. Однако для доступа по индексу необходимо "перебрать" все элементы и найти нужный индекс. Так же при использовании LinkedList следует помнить про затраты памяти на хранение связи между элементами.
В чем особенность Map в сравнении с Set и List?
Map не является наследником интерфейсов Collection или Iterable. Так же Map хранит данные в виде ключ-значение. Соответственно доступ к элементам происходит не по индексу, а по уникальному ключу. При добавлении нового элемента всегда нужно создавать для него уникальный ключ(например при использовании HashMap и не правильном заполнении ключа могут возникать коллизии - ситуации когда по ключу доступен совершенно не тот элемент который нужен).
В чем отличие между HashMap и Hashtable?
Hashtable потокобезопасна и синхронизирована, но из-за этого теряется производительность. Кроме того Вы не сможете записать парой ключ-значение null-null, в HashMap это доступно. У HashMap есть альтернатива - ConcurrentHashMap которая является потокобезопасной. В целом Hashtable более старый класс и появился в Java до введения Collection framework в целом и HashMap в частности.
Какая есть особенность у Queue? Какие порядки упорядочивания элементов Queue вы знаете?
Queue - коллекция, хранящая элементы в порядке очереди. Выделяют два порядка для упорядочивания элементов - LIFO(last-in-first-out) и FIFO(first-in-first-out) - основные отличия между ними в том что при LIFO элемент который был вставлен последний, первый же и будет возвращен/удален. При FIFO первый вставленный элемент будет возвращен(методы element() и peek()) либо удален(remove() и poll()).
Multithreading
Многопоточность - важнейшая тема при собеседовании на должность middle Java developer. Вот тут следует ждать и каверзных вопросов, вопросов с подвохами и перехода на более сложные темы. Крайне сложно вести разговор на равных по этой теме если Вы до этого не работали с многопоточностью или вся Ваша работа с ней заключалась в том что бы описать один поток и запустить его. Но понимание отдельных тем даст Вам необходимый баланс и Вы сможете произвести впечатление человека, который, если не досконально владеет темой, то как минимум не "плавает" в ней, а разбирается. Этот ряд вопросов поможет Вам сориентироваться в теме многопоточности и поможет Вам понять что нужно "подтянуть":
Какими способами можно создать потоки в Java?
В Java доступны три варианта создания потока из класса - расширить класс Thread либо реализовать интерфейсы Callable или Runnable.
При использовании Thread мы запускаем поток методом start(), а описываем логику выполнения в методе run().
При использовании Runnable мы должны вызвать метод run(), а у Callable - метод call(). Так как и Runnable и Callable - интерфейсы, мы определим логику выполнения внутри их методов(Runnable и Callable являются функциональными интерфейсами которые имеют только один метод - run() и call() соответственно). Разница в этих двух интерфейсов в том что Callable возвращает результат.
Что такое монитор?
В случае если мы, например, имеем синхронизированный метод(помеченный ключевым словом syncronized
) и один из наших потоков заходит в этот метод, то этот поток блокирует этот метод для других потоков и любой другой поток которому нужно будет воспользоваться нашим методом будет "ждать" пока первый поток не закончит свою работу с методом. Про такую ситуацию говорят: "данный метод занят монитором". Монитор в Java - объект, который обеспечивает правильную работу в многопоточной среде - отметка что синхронизированный блок кода временно стал недоступен, отметка что блок кода стал доступен после выполнения, ожидание если синхронизированный блок занят другим потоком.
Какие есть способы синхронизации в Java?
В Java существует несколько способов синхронизации:
по методу/блоку инициализации - с помощью ключевого слова
syncronized
по переменной - используя ключевое слово
volatile
методы wait/notify/notifyAll
используя классы из пакета java.util.concurrent - в этом пакете собраны классы работа которых основана на атомарных операциях.
В чем разница между sleep() и wait(), notify() и notifyAll() методами?
Метод sleep()
заставляет поток "заснуть" на определенное время(указывается в миллисекундах) после чего поток продолжит свою работу. Метод wait()
освобождает монитор занятый потоком так что другие потоки могут использовать указанный блок кода и поток переходит в состояние waiting - поток будет ждать вызова метода notify()
или notifyAll()
другим потоком. Разница между notify()
и notifyAll()
в том что notify()
"высвободит" один поток(какой именно определить нельзя) а notifyAll()
"освободит" все потоки из состояния waiting в состояние running.
Что такое Dead lock?
Случай когда у нас выполняются два потока(A, B) и наш первый поток(А) заблокировал метод a() и второй поток(В) заблокировал метод b() и в то же время поток А пытается получить доступ к методу b(), а поток B пытается получить доступ к методу а() называют dead lock.
Зачем используют потоки-демоны в Java?
Потоки-демоны это "служебные" потоки, которые работают в фоновом процессе. Они служат для "обеспечения всем необходимым" основные потоки выполнения. В случае завершения всех основных потоков потоки-демоны завершатся автоматически, не дожидаясь окончания их выполнения.
Что такое Future в Java?
Future - это интерфейс Java который находится в пакете java.util.concurrent. Future представляет методы для определения того была ли задача выполнена, ожидание выполнения для получения результата, получение результата уже выполненной задачи. В глобальном плане Future можно описать следующим образом - мы определяем задачу для Future, Future выполняет эту задачу независимо от нас, мы получаем результат.
OOP
Java язык объектно-ориентированного программирования, значит и ООП будет рассмотрен уже под более детальным углом. Если на junior уровень вам было достаточно рассказать про три основные принципы ООП, то для middle Вы можете смело поправить собеседника фразой "А их разве всего три? Куда тогда деть абстракцию?". Ниже приведен ряд вопросов для того что бы Вы поняли чего Вы не знаете и что бы Вам стало понятнее что гуглить.
Дайте определение абстракции
Абстракция - процесс выделения общих значений и характеристик объекта, исключая незначительные, которые будут определены в конкретных наследниках.
В чем преимущество ООП?
Главный плюс ООП подхода в том что мы характеризуем и описываем реальные объекты из мира - счет в банке, товар в магазине, машина и прочее. Так же ряд преимуществ нам дает наследование, полиморфизм, инкапсуляция и абстракция. Так наследование позволяет нам уйти от повторного написания одного и того же кода, абстракция позволяют нам выделить общие характеристики, а полиморфизм дает возможность использовать эти общие характеристики для разных реализаций.
В чем разница между композицией и агрегацией?
Агрегация - процесс при котором мы не строго связываем объекты, то есть наш корневой объект может существовать и правильно функционировать и без инициализации объектов-полей.
Композиция - процесс при котором мы связываем объекты строго, что значит что объект не только является частью другого объекта, но и не может быть частью других объектов.
Для полного понимания следует обратиться к примерам: наш корневой объект - машина(Car
). У машины есть двигатель(Engine
) и пассажиры(Passenger[]
). Мы можем высадить всех пассажиров(стереть массив Passenger
, либо самому массиву, либо каждому месту передать значение null
) и машина будет функционировать и без них - это называют агрегацией. В то же время машина не может функционировать без двигателя и данный конкретный двигатель не может "обслуживать" другую машину - если наша Car
Нonda Сivic, то у нее двигатель может быть только 2л и на Honda Accord мы его уже не поставим - это называется композиция.
Что такое динамическое связывание?
Что бы ответить на этот вопрос, необходимо понимать что такое само по себе связывание. И так, связывание - это наличие связи между ссылкой и кодом. Пример: ссылка на которую Вы ссылаетесь привязана к коду в котором она определена. Так же и метод привязан к месту в коде в котором он определен.
Что же такое динамическое связывание? Динамическое связывание означает что метод привязывается к конкретному коду в момент вызова, на этапе выполнения программы, на этапе создания объектов, а не при компиляции программы в байт-код.
Перечислите SOLID принципы
SOLID - это аббревиатура. Расшифровывается так:
S - Single Responsibility - означает что класс должен отвечать только за операции одного типа.
O - Open-Closed - описываемый класс должен быть открыт для расширения, но закрыт для изменений.
L - Liskov Substitution - если наш класс А является наследником класса В, то любой объект класса В может быть заменен объектом класса А без негативных последствий и нарушения функционала.
I - Interface Segregation - класс должен выполнять только те функции и задачи которые на него возложены, в ином случае это производит к потере ресурсов и появлению багов.
D - Dependency Inversion - зависимости самого низкого уровня не должны зависеть от зависимостей высшего уровня и наоборот - зависимости высшего уровня НЕ могут существовать без зависимостей низшего уровня.
Что значит Liskov Substitution?
Рассмотрим ситуацию когда мы имеем класс А - пусть это будет класс грузовик(Truck
) и его наследник прицепной грузовик(Trailer
). Назначение что одного, что другого - перевозка грузов. Используя принцип подстановки Барбары Лисков мы можем заменить любой Truck
на Trailer
без потери производительности, без негативных последствий и нарушений функционала в любом месте в программе.
SQL
Java - язык для работы с большими объемами данных. Все эти данные хранятся в базах данных разного рода. Безусловно, NoSQL базы сейчас обрели популярность и встречаются в проектах все чаще. Но 80% существующих проектов работают именно с реляционной моделью. Секрет этого весьма прост - почти все Java проекты - высоконагруженные системы, требующие обработки большого количества данных и средства Java, в целом, конечно справляются с возложенными задачами, но аппаратная часть требует больших затрат на обработку этих данных. Тут нам и помогает SQL готовый принять на себя часть этих действий, тем самым облегчая жизнь для самой Java. Разные сервера баз данных предлагают разный функционал, но базовые вещи выделяются во всех и как раз они и приведены в этих вопросах:
Что такое хранимая процедура?
Хранимая процедура - это набор инструкций который следует выполнить с данными. Например, если мы сохраняем купленный товар, нам надо проверить есть ли этот товар в наличии, есть ли на товар скидка, нет ли предзаказа на данный товар и так далее и на основании этого решить сохранять купленный товар или нет. Мы можем нагрузить наш код проверками, можем даже обернуть это все в одну транзакцию, но гораздо правильнее будет инкапсулировать все эти проверки в хранимую процедуру и вызывать ее в определенный момент не заботясь о проверках.
Какие вы знаете основные свойства транзакции?
Основные свойства транзакций баз данных сгруппированы и представлены в виде аббревиатуры ACID:
А - Atomicity(Атомарность) - гарантирует нам что каждая транзакция будет выполнена полностью, либо не будет выполнена совсем.
С - Consistency(Согласованность) - каждая успешная транзакция фиксирует только допустимые результаты не нарушая консистентность базы. Иными словами если мы сохраняем записи в разные связанные таблицы мы можем выбрать путь сохранения в каждую таблицу по отдельности, но в таком случае нам придется следить за успешным выполнением каждой из запросов что бы не нарушить целостность базы или же мы можем обернуть все запросы в одну транзакцию и не беспокоиться о том что при одной не успешной транзакции мы не должны проводить ни каких дополнительных манипуляций.
I - Isolation(Изолированность) - при выполнении одной транзакции параллельные транзакции не должны оказывать влияния на результат.
D - Durability(Надежность) - если система дала ответ об успешной транзакции, то мы не должны переживать о том что транзакция будет отменена при любом сбое. Транзакция успешно завершена, в ходе выполнения программы выпадает критическая ошибка, но транзакция уже выполнена и данные сохранены.
Что такое индексы? Как и где их применяют?
Индексы в БД - это специальные таблицы, которые используются поисковым двжком БД. В целом, индексы в БД схожи с оглавлением в книге. В случае если нам приоритетен поиск по таблице, а не вставка или изменение, мы можем создать индекс как для таблицы в целом так для одной либо нескольких столбцов. Выбор столбцов, ровно, как и типа индекса(одноколоночный/многоколоночный) зависит от того что именно, мы чаще всего будем использовать в условном операторе.
Что означает нормализация базы данных?
Нормализация БД - процесс при котором мы организовываем данные в базе, путем создания новых таблиц и связей между ними. Каждый шаг должен проходить в соответствии с правилами обеспечивающими защиту данных. В конечном итоге мы должны получить гибкую базу данных, без избыточности и несогласованных зависимостей.
Выделяют шесть нормальных форм баз данных. Переходя, например, от первой нормальной формы ко второй мы получим более гибкую базу, разделенную необходимыми связями между таблицами позволяющую гибко использовать тот или иной функционал.
Разница между HAVING и WHERE?
Самое главное отличие - используя HAVING
мы можем писать условие с использованием агрегатных функций. СHAVING
мы должны использовать GROUP BY
так как HAVING
используется после формирований групп. То есть, сначала используется фильтр WHERE
, затем формируются группыGROUP BY,
после чего можно накладывать агрегации на условие HAVING
. Следовательно - полностью заменить WHERE
мы не можем так как на этапе исполнения WHERE
мы еще не имеем групп по которым мы сможем фильтровать. А на момент выполнения HAVING
мы уже имеем необходимые группы. Это спецификация выполнения SQL запроса.
Spring Framework
Spring хорош не только тем что дает нам необходимые механизмы для создания приложений(подчеркну - не только web! Сейчас Spring используется повсеместно и даже какие либо не сложные десктопные приложения лучше создавать используя Spring), но и сама концепция Spring, ее понимание, не только владение аннотациями Spring, а и понимание того как они вставляются, расширяет наш кругозор в Java. Например, IoC и DI - паттерны проектирования, которые используются не только в Spring. Знание того что использует Spring под коробкой даст вам необходимый уровень на собеседовании не только по теме самого Spring, но и Java в целом.
Что такое IoC? Как это используется в Spring?
IoC - один из принципов ООП. Расшифровывается как Inversion of Control и дает нам возможность просто описать класс, не заботясь о его инициализации. Иными словами - мы создаем классы, отдаем эти класс под управление системой, а система уже сама создает экземпляры этого класса и сама решает какой экземпляр и где его использовать.
Например, мы описываем класс, помечаем его аннотацией и далее уже можем его использовать в том или ином контексте, не озадачиваясь тем что нам еще необходимо его правильно проинициализировать, либо этот класс должен быть singlton, либо еще чем то. Мы просто его используем. И все.
Spring использует IoC-контейнер для инициализации классов, контроля за их использованием. Когда мы помечаем один из классов как @Service
мы "отдаем" этот самый класс под власть Spring и дальше сам Spring будет отвечать за создание экземпляра этого класса и внедрение этого самого экземпляра в нужном месте.
Что такое AOP? Как это используется в Spring?
АОР - аспектно-ориентированное программирование, парадигма программирования, призванное решить те задачи для которого ООП кажется избыточным. В основе идеи лежит выделение сквозной функциональности. Грубо говоря - мы выносим наш функционал, не относящийся к бизнес логике в отдельное место и даем ему набор правил когда и с кем работать. Сумбурно? Пример: мы не можем писать код без логов. Но логи - это не часть бизнес логики, это вспомогательный функционал. Мы можем описать всю логику логов в отдельном классе и затем каждый раз инициализировать этот класс для выведения лога или же мы можем создать отдельный класс(аспект) и навесить набор правил когда и где использовать этот код. Имеем класс Service, метод method() внутри и аспект LogAspect. Используя аннотации мы можем указать методам внутри LogAspect что они должны быть вызваны перед, либо после вызова Service.method(). Так же мы можем указать выполнение после возврата результата либо после ошибки.
Spring использует АОР, например, при проверке security при доступе на тот или иной эндпоинт.
Что такое Spring Bean?
Spring Bean - самый обычный объект Java. Можно сказать, что это обыкновенный POJO, с одной единственной оговоркой - этот объект управляется Spring и только им.
Жизненный цикл Spring Beans?
Жизненным циклом бина в Spring управляет контейнер Spring. После запуска контейнера он начинает создавать необходимые бины(компоненты) и внедрять зависимости. Когда контейнер завершает свою работу уничтожаются и бины связанные с ним. Весь цикл жизни бина можно разделить на 6 этапов:
Инстанцирование объекта - технический старт жизни любого объекта, работа конструктора.
Установка свойств и внедрение зависимостей - выполнение конфигурационных свойств бина и внедрение необходимых ему зависимостей.
Уведомление aware-интерфейсов - если бин реализует
Aware
интерфейс, он будет вызываться путем передачи имени бинаset*()
метод.Пре-инициализация - метод
postProcessBeforeInitialization()
интерфейсаBeanPostProcessor
.Инициализация - сначала выполняется метод бина с аннотацией
PostConstruct
, затем методafterPropertiesSet()
в случае если бин реализует InitializingBean, методinit()
.Пост-инициализация - метод
postProcessAfterInitialization()
интерфейсаBeanPostProcessor
.
Какие есть scope Spring Beans?
Scope бинов - области видимости бинов. Последняя версия Spring(на сентябрь 2022 - 5.3.19) включает в себя шесть областей видимости:
Singleton - область видимости установленная по умолчанию, в случае если не установлен никакая другая видимость. Работает как любой паттерн проектирования Singleton.
Prototype - означает что каждый раз при обращении к контейнеру будет возвращен разные объекты.
Request - создает бин для одного HTTP запроса.
Session - аналогичен Request, но работает на уровне сессии.
Application - жизненный цикл ServletContext.
Websocket - создает бин для сессии веб-сокета
У вас несколько бинов реализующих один интерфейс. Какой из них будет внедрятся?
Для правильного внедрения зависимостей существуют несколько способов и подходов. Самый первый из них - аннотация @Primary
означает что данный бин будет внедряться по умолчанию. Так же существует аннотация @Qualifier
- позволяет указать имя бина который необходим в данном месте. Так же мы можем внедрять list/map бинов. При указании имен для всех бинов-наследников одного интерфейса мы можем внедрить map где ключом будет имя бина, а значением сам бин. При внедрении list мы получим список всех бинов.
Как объявить сервис в Spring? Назовите все способы которые знаете
Сервис в Spring - часть бизнес логики, но на самом абстрактном уровне для самого Spring все бины мало чем отличаются - каждый из них это, в первую очередь, это @Bean
который можно объявить в классе конфигураций. Далее мы можем объявить наш класс как @Component
. Используя аннотации мы можем объявить наш класс @Service
что "облегчит" работу Spring при инициализации бина(все бины инициализируются в очередности от тех кто не требует ни каких внедрений и до тех кто "не может жить" без зависимостей. Сервисные слои инициализируются "посередине" и мы даем явно понять Spring когда создавать этот бин). Кроме того мы можем объявлять бины используя xml конфигурацию Spring.
Какой класс в Spring отвечает за анализ входящих http-запросов и их направления в определенный контроллер?
В Spring за "разведение" http-запросов по соответствующим контейнерам отвечает класс DispatcherServlet. После получения запроса DispatcherServlet обращается к интерфейсу HandlerMapping, который и рассказывает DispatcherServlet какой именно котроллер отвечает за этот запрос. После обращения к контреллеру DispatcherServlet, получивший имя представления(View), обращается к ViewResolver для получения View по его имени. После создания View DispatcherServlet отправляет данные Модели в View который и отобразится в браузере.
Что такое Spring Security? В чем разница между авторизацией и аутентификацией?
Spring Security - часть Spring Framework представляющий механизмы для контроля за авторизацией пользователей. Для управления Spring Security необходимо создать конфигурационный класс-наследник WebSecurityAdapter.
Аутентификация - процедура проверки подлинности, например проверка подлинности пользователя путем сравнения введенного им пароля с паролем, сохраненным в базе данных
Авторизация - предоставление определенному лицу или группе лиц прав на выполнение определенных действий.
Подведем итог
Я не гарантирую что каждый из этих вопросов попадется Вам на собеседовании, но внимательно прочитав эту статью вы сможете определить ряд вопросов для себя и уменьшить круг поисков. Более того, возможно, на собеседовании уделяться время будет как раз таки другим технологиям - микросервисной архитектуре, работе облачными технологиями, работе с Docker, либо Вас будут гонять по NoSQL базам данных. Но будьте уверены - темы из в этой статьи будут затронуты тем или иным образом на собеседовании. Так же не затронул банальные вещи типа web, паттерны проектирования, логирование и тому подобные вещи которые Вы и так должны знать, более того Вы должны знать, что Вы должны это знать! Спасибо за внимание :-)