Spring Flashcards
Что такое Spring Framework? На чем он базируется?
Spring — это фреймворк с открытым исходным кодом для разработки приложений на Java. Фреймворк нацелен на упрощение использования Java в разработке и улучшение практики программирования.
Spring - крупный фреймворк, потому что создатели этого фреймворка ухитрились охватить практически все аспекты программирования промышленных Java-приложений.
Составные части (компоненты) Spring Framework:
* IoC (Inversion of Control) контейнер;
* AOP-фреймворк (включая интеграцию с AspectJ);
* Data Access фреймворк;
* Transaction management;
* MVC-фреймворк;
* Remote Access фреймворк;
* Batch processing;
* Spring Security;
* Remote Management;
* Messaging-фреймворк;
* Testing-фреймворк.
Каковы преимущества использования Spring?
- Легкость — он относительно легкий, когда дело касается размера и прозрачности. Базовая версия Spring Framework составляет около 2 МБ.
- Инверсия управления (Inversion of control, IOC) — слабая связанность достигается в Spring с использованием техники инверсии управления. Объекты предоставляют свои зависимости вместо того, чтобы создавать или искать зависимые объекты.
- Аспектно-ориентированность — Spring поддерживает аспектно-ориентированное программирование и обеспечивает согласованную разработку, отделяя бизнес-логику приложения от системных служб.
- Контейнеры — Spring Container создаёт объекты, связывает их вместе, настраивает и управляет ими от создания до момента удаления.
- MVC Framework — это хорошо спроектированный веб-фреймворк MVC, который обеспечивает альтернативу другим излишне спроектированным или менее популярным веб-фреймворкам.
- Управление транзакциями — Spring имеет согласованный интерфейс управления транзакциями, который может масштабироваться до локальной транзакции или глобальных транзакций.
- Обработка исключений — Spring предоставляет удобный API для преобразования исключений, связанных с конкретной технологией (например, вызванных JDBC, Hibernate или JDO) в согласованные, непроверенные исключения.
Какие подпроекты Spring вы знаете? Кратко опишите их.
- Core — ключевой модуль, обеспечивающий основные части платформы, такие как IoC или DI.
- JDBC - включает уровень абстракции JDBC, который устраняет необходимость кодирования JDBC для баз данных конкретных поставщиков.
- Интеграция ORM — обеспечивает уровни интеграции для популярных API объектно-реляционного сопоставления, таких как JPA, JDO и Hibernate.
- Web - веб-ориентированный модуль интеграции, который обеспечивает многокомпонентную загрузку файлов, прослушиватели сервлетов и функции контекста веб-приложений.
- Платформа MVC - веб-модуль, реализующий шаблон проектирования Model View Controller.
- Модуль АОП - реализация аспектно-ориентированного программирования, позволяющая определять чистые перехватчики методов и точки.
Что такое Inversion of control и какие реализации существуют? В чем идея инверсии управления?
Инверсия управления — это принцип разработки программного обеспечения, который передает управление объектами или частями программы контейнеру или фреймворку. Чаще всего мы используем его в контексте объектно-ориентированного программирования.
В отличие от традиционного программирования, в котором наш пользовательский код обращается к библиотеке, IoC позволяет фреймворку управлять потоком программы и выполнять вызовы нашего пользовательского кода. Для этого фреймворки используют абстракции со встроенным дополнительным поведением. Если мы хотим добавить собственное поведение, нам нужно расширить классы фреймворка или добавить наши собственные классы.
Преимущества этой архитектуры:
* отделение выполнения задачи от ее выполнения
* упрощение переключения между различными реализациями
* большая модульность программы
* более простое тестирование программы за счет изоляции компонента или имитации его зависимостей и предоставления компонентам возможности взаимодействовать через контракты.
Есть несколько реализаций инверсии управления:
* шаблон проектирования стратегии
* шаблон фабрики
* шаблон локатора сервисов
* внедрение зависимостей.
В чем разница между IOC и Dependency Injection? Преимущества Dependency Injection?
Inversion of Control (инверсия управления) — это некий абстрактный принцип, набор рекомендаций для написания слабо связанного кода. Суть которого в том, что каждый компонент системы должен быть как можно более изолированным от других, не полагаясь в своей работе на детали конкретной реализации других компонентов.
Dependency Injection (внедрение зависимостей) — это одна из реализаций этого принципа; это шаблон, который мы можем использовать для реализации IoC, представляет собой общую концепцию, утверждающую, что мы не создаем наши объекты вручную, а вместо этого описываем, как они должны создаваться. Затем контейнер IoC будет создавать экземпляры необходимых классов, если это необходимо.
Внедрение внедрения зависимостей дает вам следующие преимущества:
* Возможность повторного использования кода
* Легкость рефакторинга
* Легкость тестирования
Что такое IOC Spring контейнер?
IoC-контейнер — это какая-то библиотека, фреймворк, программа, которая позволит вам упростить и автоматизировать написание кода с использованием данного подхода на столько, на сколько это возможно.
Контейнер IoC является общей характеристикой фреймворков, реализующих IoC.
В среде Spring интерфейс ApplicationContext представляет контейнер IoC. Контейнер Spring отвечает за создание, настройку и сборку объектов, известных как bean -компоненты, а также за управление их жизненными циклами.
Платформа Spring предоставляет несколько реализаций интерфейса ApplicationContext: ClassPathXmlApplicationContext и FileSystemXmlApplicationContext для автономных приложений и WebApplicationContext для веб-приложений.
Для сборки bean-компонентов контейнер использует метаданные конфигурации, которые могут быть в форме XML-конфигурации или аннотаций.
Вот один из способов вручную создать экземпляр контейнера:
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
Чтобы установить атрибут элемента в приведенном выше примере, мы можем использовать метаданные. Затем контейнер будет читать эти метаданные и использовать их для сборки bean-компонентов во время выполнения.
Как Spring загружает классы из контекста?
Используется стандартный механизм загрузки классов Java: выполняется обход загрузчиков классов в попытке найти искомый класс среди загруженных ранее, и, если класс удалось найти не удалось, происходит попытка загрузить его.
Какие виды внедрения зависимости есть? Какая разница меду ними?
Существует несколько различных вариантов внедрения bean-компонентов Spring:
* внедрение через сеттер;
* внедрение через конструктор;
* внедрение через поле.
Рекомендуемый подход — использовать аргументы конструктора для обязательных зависимостей и сеттеры для необязательных. Это связано с тем, что внедрение конструктора позволяет вводить значения в неизменяемые поля и упрощает тестирование.
@Autowired может использоваться вместе с конструкторами, сеттерами или любым другими методами. Когда Spring находит @Autowired на методе, Spring автоматически вызовет этот метод, после создания экземпляра бина. В качестве аргументов, будут подобраны подходящие объекты из контекста Spring.
Что такое контекст приложения (ApplicationContext)?
ApplicationContext - это главный интерфейс в Spring-приложении, который предоставляет информацию о конфигурации приложения. Он доступен только для чтения во время выполнения, но может быть перезагружен при необходимости и поддержке приложением. Число классов, реализующих ApplicationContext интерфейс, доступны для различных параметров конфигурации и типов приложений.
ApplicationContext создаёт и хранит экземпляры классов вашего приложения, определяет их зависимости друг с другом и автоматически их задаёт. Для того чтобы Spring создал контекст с экземплярами классов, ему нужно предоставить дополнительную информацию — мета-данные, из каких классов/объектов состоит приложение, как они создаются, какие у них есть зависимости и т. д.
Итого: Spring Context + мета-данные = работающее приложение.
Приоритет применения конфигураций.
Конфигурацию можно выполнить с помощью XML-файлов, аннотаций или java-code.
1. Xml конфигурация — ClassPathXmlApplicationContext(”context.xml”);
2. Конфигурация через аннотации с указанием пакета для сканирования — AnnotationConfigApplicationContext(”package.name”);
3. JavaConfig — конфигурация через аннотации с указанием класса (или массива классов) помеченного аннотацией @Configuration — AnnotationConfigApplicationContext(JavaConfig.class).
Можем ли мы иметь несколько файлов конфигурации Spring в одном проекте?
Да, в крупных проектах рекомендуется иметь несколько конфигураций Spring для повышения удобства обслуживания и модульности.
Мы можем загрузить несколько файлов конфигурации на основе Java:
@Configuration
@Import({MainConfig.class, SchedulerConfig.class})
public class AppConfig {}
Или мы можем загрузить один файл XML, который будет содержать все остальные конфиги:
ApplicationContext context = new ClassPathXmlApplicationContext(“spring-all.xml”);
И внутри этого XML-файла у нас будет следующее:
<import></import>
<import></import>
Какой способ конфигурации выбрать и почему? (вопрос философский)
Предпочитаю аннотации, если кодовая база хорошо описывается такими элементами, как @Service, @Component, @Autowired. Однако, когда дело доходит до конфигурации, у меня нет каких-либо предпочтений. Я бы оставил этот вопрос команде.
Почему не нужно сейчас уже указывать аннотацию Autowired? Неявное внедрение.
Spring умеет анализировать наш код, он читает класс, видит, что у него есть только один конструктор, затем он пытается определить какой у него аргумент, и если этот аргумент находится в Spring-контейнере, то есть кандидат на внедрение зависимости есть, он его успешно внедряет.
(Бин нашего класса должен быть в файле конфигурации и наш зависимый класс, тоже должен быть объявлен бином в файле конфигурации. Если удалить что-то – идея будет ругаться).
Мы можем поставить @Autowired, но она будет избыточна, и от нее ничего не поменяется.
Что такое Spring beans?
Spring beans — это экземпляры объектов, которыми управляет Spring Container. Они создаются и подключаются фреймворком и помещаются в контейнер, откуда вы можете их позже извлечь.
Во-первых, необходимо создать экземпляр компонента Spring на основе определения компонента Java или XML. Также может потребоваться выполнить некоторую инициализацию, чтобы привести его в пригодное для использования состояние. После этого, когда бин больше не нужен, он будет удален из контейнера IoC.
Что содержится в определении bean-компонента?
Определение bean-компонента содержит информацию, называемую метаданными конфигурации, которая необходима контейнеру, чтобы знать следующее:
*Как создать bean;
*Подробности жизненного цикла bean;
*Зависимости bean.
Что такое Bean wiring?
Bean wiring — это действие по созданию ассоциаций между компонентами приложения (beans) в контейнере Spring. «Связка» (wiring) — это то, что является внедрением зависимостей. Это означает, что вы можете просто сказать: «Мне нужна эта вещь», и фреймворк будет следовать определенным правилам для получения этого объекта.
Какова область действия по умолчанию у bean-компонента в Spring framework?
Область действия bean-компонента по умолчанию — Singleton (шаблон проектирования).
Являются ли Singleton Beans потокобезопасными?
Нет, singleton bean-компоненты не потокобезопасны, поскольку потокобезопасность связана с выполнением, тогда как singleton — это шаблон проектирования, ориентированный на создание. Безопасность потоков зависит только от самой реализации компонента.
Что такое BeanDefinition и зачем он нужен?
Для того чтобы наша конфигурация была понята Spring’ом существует XmlBeanDefinitionReader. Это внутренний компонент Spring’a, который сканирует xml и на основе того, что мы там написали создает BeanDefinition’ы. BeanDefinition – это объект, который хранит в себе информацию о бине. Сюда входит: из какого класса его (бин) надо создать; scope; установлена ли ленивая инициализация; нужно ли перед данным бином инициализировать другой и иные проперти, которые описаны в xml. Все полученные BeanDefinition’ы складываются в HashMap, в которой идентификатором является имя бина (установленное вами или присвоенное спрингом) и сам BeanDefinition объект. После того, как все BeanDefinition’ы созданы на сцену выходит новый герой – BeanFactory. Этот объект итерируется по HashMap’e с BeanDefinition’ами, создает на их основе бины и складывает в IoC контейнер. Здесь есть нюанс, на самом деле, при старте приложения, в IoC контейнер попадут бины, которые имеют scope Singleton, остальные же создаются тогда, когда они нужны (prototype, request, session).
BeanDefinition — это специальный интерфейс, через который можно получить доступ к метаданным будущего бина. В зависимости от того, какая у вас конфигурация, будет использоваться тот или иной механизм парсирования конфигурации.
Что такое scope? Какие есть, зачем нужен?
singleton – объект создается один раз для каждого контейнера Spring IoC, при последующих внедрениях переиспользуется. Полезен для большинства случаев: различные сервисы, объекты без состояния, неизменяемые объекты.
prototype – при каждом внедрении фабрика бинов создает новый объект. Нужен для изменяемых бинов с состоянием.
Spring Web добавляет 4 дополнительных скоупа, которые делают бин синглтоном в пределах обработки одного сетевого запроса (request), клиентской сессии (session), контекста сервлета (application) и вебсокет-сессии (websocket).
Какой механизм использует Spring для разбора конфигураций?
У каждой реализации контекста свой инструментарий, но в основном используется сканирование. До момента создания BeanDefinition, мы не пытаемся загружать классы: сначала происходит сканирование по указанным параметрам, а после создаются подходящие BeanDefinition’ы на основании результатов сканирования. Затем уже постпроцессоры пытаются донастроить сам BeanDefinition, загрузить к нему класс и т.д.
Для чего нужен Component Scan?
Если понимать, как работает Component Scan, то легко можно понять Spring.
Первый шаг для описания Spring Beans это добавление аннотации — @Component, или @Service, или @Repository.
Однако, Spring ничего не знает об этих бинах, если он не знает где искать их. То, что скажет Spring где искать эти бины и называется Component Scan. В @ComponentScan вы указываете пакеты, которые должны сканироваться.
Spring будет искать бины не только в пакетах для сканирования, но и в их подпакетах.
В чём отличие между @Component и @ComponentScan?
@Component и @ComponentScan предназначены для разных целей
@Component помечает класс в качестве кандидата для создания Spring бина.
@ComponentScan указывает, где Spring искать классы помеченные аннотацией @Component или его производной.
В чём разница между @Component, @Service и @Repository аннотациями?
Все они определяют бины Spring. Однако между ними всё же есть разница.
@Component — аннотация для любого компонента фреймворка.
@Repository — компонент, который предназначен для хранения, извлечения и поиска. Как правило, используется для работы с базами данных.
@Service — фасад для некоторой бизнес логики