Spring Flashcards
Inversion of Control – принцип при котором контроль за выполнением программы переходит от программиста к фреймворку.
Dependencies -другие объекты (как правило других классов), с которыми работает и чью функциональность использует текуущий объект.
Dependency Injection является способом реализации принципа IoC в Spring через рефлексию:
IoC-контейнер отвечает за управление жизненным циклом объектов: создание, вызов методов инициализации и конфигурирование объектов через связывание их между собой.
Таким образом, задача программиста - сконфигурировать контейнер, а дальше он всё сделает сам.
Конфигурирование контейнера осуществляется через внедрение аннотаций, через java-code, XML-файлы, и через смесь этих опций.
Spring определяет и внедряет зависимости через (на выбор):
- параметры корструктора
- параметры статического метода реализации (фабричный метод)
- сеттеры (<property/>
)
https://habr.com/ru/post/470305/
Что такое IoC контейнер?
Container создаёт объекты, связывает их вместе, настраивает и управляет ими от создания до момента уничтожения.
Объекты хранятся в ассоциативном массиве.
Бины создаются при “поднятии” контекста все сразу. Если не указана стратегия инициализации.
2 типа контейнеров:
1) Spring BeanFactory Container обеспечивает базовую поддержку DI.
BeanFactory обычно используется тогда, когда ресурсы ограничены (мобильные устройства). Поэтому, если ресурсы не сильно ограничены, то лучше использовать ApplicationContext.
2) Spring ApplicationContext Container является более сложным и более продвинутым Spring Container-ом. Наследует BeanFactory и так же загружает бины, связывает их вместе и конфигурирует их определённым образом. Но кроме этого предоставляет дополнительные возможности, например AOP и транзакции.
WebApplicationContext - расширяет ApplicationContext и используется в веб-приложениях.
Что такое Bean в спринге?
Бин (bean) — это обычный, как правило не POJO объект, котрый при поднятии контекста будет создан спрингом.
По умолчанию бин задается как синглтон.
prototype бины не хранятся в контейнере, они настраиваются и отдаются наружу, при следующем вызове это повторяется.
Таким образом все публичные переменные класса могут быть изменены одновременно из разных мест, а значит бин - не потокобезопасен. Однако поменяв область действия бина на request, prototype, session он станет потокобезопасным, но это скажется на производительности.
Расскажите про аннотацию @Bean?
Аннотация @Bean используется для указания того, что данный метод создает, настраивает и возвращает готовый объект, управляемый IoC-контейнером.
Как правило используется в классах с аннотацией @Configuration,
Может использоваться и в классах с аннотацией @Component (или ее наследниках).
Имеет следующие свойства:
- name - имя (уникальный идентификатор) бина;
- initMethod - имя метода для вызова во время инициализации бина;
- destroyMethod - имя метода для вызова во время удаления бина из контекста;
- autowireCandidate - является ли этот бин кандидатом на автоматическое внедрение в другой бин.
Расскажите про аннотацию @Component?
Это аннотация Spring Framework, ею мы помечаем класс, если хотим, чтобы из этого класса был создан бин.
Можно указать имя (Id) для создаваемого бина, а можно не указывать, тогда по умолчанию именем будет название класса с маленькой буквы.
Аннотация @Component имеет наследников:@Configuration, @Repository, @Service и @Controller. Все они являются частными случаями использования @Component для класса конфигурации, слоёв DAO, сервиса и контроллера MVC соответственно.
@Component - Spring определяет этот класс как кандидата для создания bean.
@Service - класс содержит бизнес-логику и вызывает методы на уровне хранилища. Ничем не отличается от классов с @Component.
@Repository - указывает, что класс является слоем, взаимодействующем с ДБ. Задача @Repository заключается в том, чтобы отлавливать исключения персистентности и приводить их к подклассам DataAccessExeption спринга. Для этого Spring оборачивает эти классы в прокси, и в контекст должен быть добавлен класс
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { return new PersistenceExceptionTranslationPostProcessor();}. - спринг делает это автоматически в большинстве случаев.
@Controller - указывает, что класс выполняет роль контроллера MVC. DispatcherServlet просматривает такие классы для поиска @RequestMapping.
@RequestMapping используется для мапинга (связывания) с URL для всего класса или для конкретного метода обработчика.
@Configuration - означает, что класс будет содержать bean definition методы с аннотацией @Bean
Чем отличаются аннотации @Bean и @Component?
Аннотация @Component (как и @Service и @Repository) используется для автоматического обнаружения и автоматической настройки бинов в ходе сканирования путей к классам.
Аннотация @Bean используется для явного объявления бина и позволяет добавить bean, уже реализованного сторонней библиотекой.
Расскажите про аннотации @Service и @Repository. Чем они отличаются?
@Service и @Repository являются частными случаями @Component. Технически они одинаковы, но мы используем их для разных целей.
Задача @Repository заключается в том, чтобы отлавливать определенные исключения персистентности и пробрасывать их как одно непроверенное исключение Spring Framework. Для этого в контекст должен быть добавлен класс PersistenceExceptionTranslationPostProcessor.
Мы помечаем бины аннотацией @Service, чтобы указать, что они содержат бизнес- логику. Так что нет никакого другого предназначения, кроме как использовать ее на уровне сервиса.
Расскажите про аннотацию @Autowired
Это аннотация Spring Framework, ею помечают конструктор, поле, сеттер-метод или метод конфигурации, параметр метода, сигнализируя, что им обязательно требуется внедрение зависимостей.
- Контейнер определяет тип объекта для внедрения.
- Контейнер ищет соответствующий тип бина у себя в контексте.
- Если есть несколько кандидатов и один из них помечен как @Primary, то внедряется он.
- Если используется @Qualifier, то контейнер будет использовать информацию из @Qualifier, чтобы понять, какой компонент внедрять.
- В противном случае контейнер внедрит бин, основываясь на его имени или ID.
- Если ни один из способов не сработал, то будет выброшено исключение, если не указать @Autowired(required = false)
При циклической зависимости, когда объекты ссылаются друг на друга, нельзя ставить над конструктором.
Начиная со Spring Framework 4.3, аннотация @Autowired для конструктора больше не требуется, если целевой компонент определяет только один конструктор.
Мы также можем указать Spring предоставить все бины определенного типа из ApplicationContext, добавив аннотацию @Autowired в поле или метод с массивом или коллекцией этого типа:
~~~
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs; }
~~~</MovieCatalog>
Даже коллекции типа Map могут быть подключены автоматически, если тип ключа - String. Ключами будут имена бинов, а значениями - сами бины:
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs){
this.movieCatalogs = movieCatalogs; }
Расскажите про аннотацию @Resource
Это как Autowired, только аннотация Java
Разница с @Autowired:
ищет бин сначала по имени, а потом по типу;
не нужна дополнительная аннотация для указания имени конкретного бина;
@Autowired позволяет отметить место вставки бина как необязательное @Autowired(required = false);
при замене Spring Framework на другой фреймворк, менять аннотацию @Resource не нужно.
Расскажите про аннотацию @Inject
@Inject (аннотация java) – аналог @Autowired (аннотация spring) в первую очередь пытается
подключить зависимость по типу, затем по описанию и только потом по имени.
Расскажите про аннотацию @Lookup
аннотация стит над методом компонента и означает, что он должен создать настроить и вернуть бин того типа, который возвращает метод.
Контейнер его заоверрайдит.
используется
- для внедрения prototype бина в singletone бин
- для процедурного внедрения зависимостей
Такой бин будет инициализирован не при поднятии контекста, а при вызове метода.
@Lookup public SchoolNotification getNotification() { return null; }
ограничения:
- когда метод находится внутри компонента, он не может быть абстрактным, так как спринг при создании бина скипает абстрактные методы
- аннотация не будет работать, если содержащий класс инициализируется через @Bean
Можно ли вставить бин в статическое поле? Почему?
Spring не позволяет внедрять бины напрямую в статические поля. Это связано с тем, что когда загрузчик классов загружает статические значения, контекст Spring еще не загружен.
Чтобы исправить это, можно создать нестатический сеттер-метод с @Autowired:
private static OrderItemService orderItemService; @Autowired public void setOrderItemService(OrderItemService orderItemService) { TestDataInit.orderItemService = orderItemService; }
Расскажите про аннотации @Primary и @Qualifier
@Qualifier применяется, если кандидатов для автоматического связывания несколько, аннотация позволяет указать в качестве аргумента имя конкретного бина, который следует внедрить.
Она может быть применена к отдельному полю класса, к отдельному аргументу метода или конструктора
@Primary тоже используется, чтобы отдавать предпочтение бину, когда есть несколько бинов одного типа, но в ней нельзя задать имя бина, она определяет значение по умолчанию.
Если присутствуют аннотации @Qualifier и @Primary, то аннотация @Qualifier будет иметь приоритет.
Как заинжектить примитив?
Для этого можно использовать аннотацию @Value. Можно ставить над полем, конструктором, методом.
Такие значения можно получать из property файлов, из бинов, и т. п.
Чтобы получить из property файла надо над конфиг классов повесить @PropertySource(“classpath:db.properties”)
@Value(“${some.key}”)
public String stringWithDefaultValue;
В эту переменную будет внедрена строка, например, из property или из view.
Кроме того, для внедрения значений можно использовать язык SpEL (Spring Expression Language).
Как заинжектить коллекцию?
Если внедряемый объект массив, коллекция или map с дженериком, то, используя аннотацию @Autowired, Spring внедрит все бины, подходящие по типу в этот массив (или другую структуру данных). В случае с map ключом будет имя бина.
Используя аннотацию @Qualifier можно настроить тип искомого бина.
Бины могут быть упорядочены, если вставляются в списки (не Set или Map) или массивы. Поддерживаются как аннотация @Order, так и интерфейс Ordered.