Что такое Spring Framework и какие основные задачи он решает?
Spring Framework - это фреймворк для разработки приложений на языке Java, который предоставляет комплексное решение для различных задач, связанных с разработкой приложений.
Основная идея заключается в том, что Spring берет на себя ответственность за создание объектов и управление ими, вместо того, чтобы доверять это процессу создания объектов в языке Java.
В рамках механизма управления жизненным циклом объектов Spring осуществляет инъекцию зависимостей, конфигурирование бинов (англ. bean configuration), управление состоянием и жизненным циклом бинов (Жизненный цикл объекта состоит из нескольких этапов, включая создание, инициализацию, использование и уничтожение.).
Основные задачи, которые решает Spring Framework, включают в себя:
Таким образом, Spring Framework предоставляет комплексное решение для различных задач, связанных с разработкой приложений на языке Java, и позволяет ускорить процесс разработки, повысить качество кода и облегчить поддержку приложения.
Как происходит конфигурирование Spring?
Конфигурирование Spring происходит через специальный файл конфигурации, который может быть в формате XML, Java-кода или аннотаций. В этом файле описываются бины (классы, объекты или компоненты), которые необходимы для работы приложения, и их свойства.
Существует несколько способов конфигурирования Spring:
После того, как файл конфигурации был создан, его необходимо загрузить в Spring контейнер при запуске приложения. Это делается с помощью специального класса ApplicationContext, который загружает конфигурацию и создает бины. Затем приложение может использовать эти бины для выполнения своей работы.
Spring также предоставляет механизмы для автоматической конфигурации, которые могут сэкономить время и упростить настройку. Например, Spring Boot предоставляет автоматическую конфигурацию для большинства приложений, которая может быть настроена с помощью специальных файлов настроек и аннотаций.
Что такое инверсия контроля (IoC) и внедрение зависимостей (DI)? Как эти принципы реализованы в Spring?
Inversion of Control –это принцип в разработке программного обеспечения, при котором управление объектами или частями программы передается контейнеру или фреймворку.принцип для написания слабосвязанного кода
Dependencies -другие объекты (как правило других классов), с которыми работает и чью функциональность использует текущий объект.
Dependency Injection является способом реализации принципа IoC в Spring через рефлексию:
DI механизм передачи классу его зависимостей
Dependency Injection (DI) - это механизм внедрения зависимостей, при котором классы не создают свои зависимости, а получают их из внешних источников, таких как Spring-контейнер.
DI механизм позволяет классам работать со своими зависимостями, не заботясь о том, как они создаются и управляются. Вместо этого класс принимает зависимости через конструктор, методы или поля, которые автоматически заполняются при создании объекта.
Spring определяет и внедряет зависимости через (на выбор):
* Конструкторы: можно помечать конструкторы аннотацией @Autowired, чтобы Spring автоматически искал подходящие бины для всех параметров конструктора и использовал их для создания экземпляра класса.
* Сеттеры: можно помечать методы-сеттеры аннотацией @Autowired, чтобы Spring автоматически внедрял бины в соответствующие поля.
* Поля: можно также помечать поля класса аннотацией @Autowired, чтобы Spring автоматически внедрял бины в эти поля.
* Методы-фабрики: можно пометить статический метод класса аннотацией @Bean, который возвращает экземпляр класса, чтобы Spring использовал этот метод в качестве фабричного метода для создания бинов.
В Spring Framework инверсия контроля достигается именно внедрением зависимостей. В Spring Framework инверсия контроля и внедрение зависимостей считаются одним и тем же.
IoC-контейнер отвечает за управление жизненным циклом объектов: создание, вызов методов инициализации и конфигурирование объектов через связывание их между собой.
Объекты, создаваемые контейнером, называются beans. Конфигурирование контейнера осуществляется через внедрение аннотаций, но есть возможность, по старинке, загрузить XML-файлы, содержащие определение bean’ов и предоставляющие информацию, необходимую для создания bean’ов.
IoC - аутсорсинг создания и управления объектами. Т.е. передача программистом прав на создание и управление объектами Спрингу
DI - аутсорсинг добавления/внедрения зависимостей. DI делает объекты нашего приложения слабо зависимыми друг от друга.
DI это частный случай IoC
IoC это принцип или методология, а DI это конкретная реализация
Что такое IoC контейнер?
IoC контейнер - это механизм, используемый в фреймворке Spring для управления жизненным циклом объектов, а также для внедрения зависимостей между объектами.
IoC Container - это объект, который занимается созданием других объектов и внедрением в них зависимостей(DI)
в IOC (Inversion of Control) контейнере объекты, или бины, хранятся в ассоциативном массиве, где ключом обычно является уникальный идентификатор (например, строковый), который позволяет получить доступ к соответствующему объекту. Это позволяет легко настраивать зависимости между бинами и обеспечивает централизованное управление созданием и конфигурированием объектов, что упрощает разработку приложений.
Контейнер Spring представляет собой реализацию принципа Inversion of Control (IoC), который состоит в том, что контроль за жизненным циклом объектов передается контейнеру, который управляет созданием, настройкой и уничтожением объектов.
В Spring Framework контейнер отвечает за создание, настройку и сборку объектов, известных как бины, а также за управление их жизненным циклом. Он (контейнер) представлен интерфейсом ApplicationContext.
Spring Framework предоставляет несколько реализаций интерфейса ApplicationContext:
* ClassPathXmlApplicationContext и FileSystemXmlApplicationContext - для автономныхприложений;
* WebApplicationContext - для веб-приложений;
* AnnotationConfigApplicationContext - для обычной Java-конфигурации, в качестве аргумента которому передается класс, либо список классов с аннотацией @Configuration, либо с любой другой аннотацией JSR-330, в том числе и @Component.
ApplicationContext может быть настроен разными способами:
* через XML-файлы,
* аннотации
* чистый Java-код.
Контейнер автоматически находит классы с аннотациями, такими как @Component, @Service и т.д., и создает объекты-бины на основе их определений. Кроме того, он позволяет внедрять зависимости между бинами с помощью аннотации @Autowired или XML-конфигурации.
Spring BeanFactory Container Это самый простой контейнер, который обеспечивает базовую поддержку DI и который основан на интерфейсе org.springframework.beans.factory.BeanFactory.
BeanFactory обычно используется тогда, когда ресурсы ограничены (мобильные устройства). Поэтому, если ресурсы не сильно ограничены, то лучше использовать ApplicationContext.
Spring ApplicationContext Container является более сложным и более продвинутым Spring Container-ом. Наследует BeanFactory и так же загружает бины, связывает их вместе и конфигурирует их определённым образом. Но кроме этого предоставляет дополнительные возможности, например AOP и транзакции. Этот контейнер определяется интерфейсом org.springframework.context.ApplicationContext.
Контейнер Spring может создавать объекты в различных скоупах, таких как Singleton, Prototype, Session и Request. Singleton обеспечивает создание единственного экземпляра объекта на уровне приложения, тогда как Prototype создает новый экземпляр каждый раз при запросе объекта. Session и Request используются в веб-приложениях и обеспечивают создание объектов на уровне сессии и запроса соответственно.
Контейнер Spring позволяет внедрять зависимости между объектами при помощи автоматического связывания (Autowiring) или явного задания зависимостей. Автоматическое связывание позволяет контейнеру Spring самостоятельно определить зависимости между объектами на основе их типа и имен, тогда как явное задание зависимостей использует аннотации, XML-конфигурацию или Java-код для определения зависимостей.
Что такое Bean в спринге?
Бин (bean) — это обычный объект. Разница лишь в том, что бинами принято называть те объекты, которые создаются и управляются IO-контейнером и живут внутри него.
@Bean - это объект со всеми необходымыми зависимостями, который был создан с помощью IoC Container
Еще можно добавить, что Bean это переиспользуемый програмный компонент
Bean Definition - это чертеж
Bean - это деталь, созданная по данному чертежу
Иначе говоря, бин — это просто один из множества объектов в вашем приложении. Бины и их зависимости отражаются в метаданных конфигурации, используемых контейнером.
По умолчанию бин задается как синглтон.
Таким образом все публичные переменные класса могут быть изменены одновременно из разных мест, а значит бин - не потокобезопасен. Однако поменяв область действия бина на request, prototype, session он станет потокобезопасным, но это скажется на производительности.
Существуют несколько требований к бину в Spring:
Расскажите про аннотацию @Bean?
Аннотация @Bean используется для указания того, что метод создает, настраивает и инициализирует новый объект, управляемый IoC-контейнером.
Как правило используется в классах с аннотацией @Configuration,
Может использоваться и в классах с аннотацией @Component (или ее наследниках).
Позволяет дополнительно определить у бина:
- name - имя (уникальный идентификатор) бина;
- initMethod - имя метода для вызова во время инициализации бина;
- destroyMethod - имя метода для вызова во время удаления бина из контекста;
- autowireCandidate - является ли этот бин кандидатом на автоматическое внедрение в другой бин.
@Configuration
public class MyConfig {
@Bean(name = "myBean", initMethod = "init", destroyMethod = "cleanup")
@Scope("prototype")
@DependsOn("dependencyBean")
public MyBean myBean() {
return new MyBean();
}
@Bean(name = "dependencyBean")
public DependencyBean dependencyBean() {
return new DependencyBean();
}
}Что такое Bean definition и metadata?
Bean definition - это описание бина, которое может содержать информацию о классе бина, его свойствах, зависимостях и других метаданных. В Spring бины создаются и настраиваются в IoC контейнере, на основе Bean definition.
Bean definition может содержать информацию о классе объекта, его свойствах, зависимостях, и других конфигурационных параметрах.
@Configuration
public class MyConfig {
@Bean
public MyBean myBean() {
MyBean bean = new MyBean();
bean.setMyProperty("myValue");
return bean;
}
}В этом примере метод myBean() является фабричным методом, который возвращает экземпляр класса MyBean. Аннотация @Bean указывает, что метод должен быть обработан IoC контейнером как Bean definition, и результат его выполнения должен быть помещен в контейнер.
Вот несколько примеров аннотаций, которые можно отнести к Bean Definition:
* @Bean - используется для объявления метода, который возвращает объект, который будет управляться контейнером Spring. Этот метод может содержать логику создания, настройки и инициализации бина.
* @Configuration - используется для указания, что класс содержит один или несколько методов, которые возвращают бины, которые нужно создать и настроить. Эта аннотация является альтернативой использованию XML-файлов конфигурации.
* @ComponentScan - указывает Spring-контейнеру, какие пакеты нужно сканировать, чтобы найти все классы, которые могут быть использованы как бины. Эта аннотация может использоваться в классах конфигурации.
* @Import - используется для импорта конфигурационных классов или Java-конфигураций в текущий контекст приложения.
* @Conditional - позволяет задать условия для создания бина. Бин будет создан только в том случае, если указанные условия выполняются.
* @Lazy - используется для указания, что бин должен быть создан только в момент, когда он первый раз используется.
Метаданные это дополнительная информация о бинах, которая может быть использована для настройки их создания и поведения.
Метаданные могут быть использованы для описания различных аспектов бина, таких как область видимости, жизненный цикл, зависимости, аспекты и т.д. Например, для управления областью видимости можно использовать аннотации, такие как @Scope, а для управления жизненным циклом - аннотации, такие как @PostConstruct и @PreDestroy.
@Component
@Scope("prototype")
public class MyBean {
@Autowired
private MyDependency dependency;
// ...
}Вот несколько примеров аннотаций, которые можно отнести к метаданным:
* @Autowired - указывает на необходимость внедрения зависимости для данного бина. Аннотация может использоваться для полей, методов и конструкторов.
* @Qualifier - используется вместе с @Autowired для разрешения неоднозначности, когда в контейнере существует несколько бинов одного типа. Она позволяет указать конкретный бин, который должен быть внедрен.
* @Value - позволяет задать значение свойства бина в виде строки. Аннотация может использоваться для полей, методов и конструкторов.
* @PostConstruct - позволяет указать метод, который должен быть вызван после создания бина, но перед тем, как он будет использован. Это может быть полезно для инициализации объектов.
* @Scope - позволяет указать область видимости бина. По умолчанию, бины создаются в области видимости singleton, но можно использовать и другие области видимости, такие как prototype, request, session и другие.
* @Profile - позволяет определить профиль, которому соответствует данный бин. Бины с определенным профилем будут созданы только в том случае, если данный профиль активен.
Расскажите про аннотацию @Component?
Это аннотация Spring Framework, ею мы помечаем класс, если хотим, чтобы из этого класса был создан бин. Именно эту аннотацию ищет Spring Framework, когда сканирует наши классы. Можно указать имя (Id) для создаваемого бина, а можно не указывать, тогда по умолчанию именем будет название класса с маленькой буквы.
Когда класс помечается аннотацией @Component, Spring автоматически создает экземпляр этого класса в качестве бина в контейнере. Это позволяет другим классам в приложении использовать этот компонент через механизм внедрения зависимостей (DI).
Аннотация @Component имеет наследников: @Repository, @Service и @Controller. Все они являются частными случаями использования @Component для слоёв DAO, сервиса и контроллера MVC соответственно.
@Component - Spring определяет этот класс как кандидата для создания bean.
@Service - класс содержит бизнес-логику и вызывает методы на уровне хранилища. Ничем не отличается от классов с @Component.
@Repository - указывает, что класс является слоем, взаимодействующем с ДБ. Задача @Repository заключается в том, чтобы отлавливать исключения персистентности и приводить их к подклассам DataAccessExeption спринга.Для этого Spring оборачивает эти классы в прокси, и в контекст должен быть добавлен класс PersistenceExceptionTranslationPostProcessor.
@Controller - указывает, что класс выполняет роль контроллера MVC. DispatcherServlet просматривает такие классы для поиска @RequestMapping.
@RequestMapping используется для мапинга (связывания) с URL для всего класса или для конкретного метода обработчика.
@Configuration - означает, что класс будет содержать bean definition методы с аннотацией @Bean. Класс, помеченный этой аннотацией, должен быть открытым и не должен быть final. Конструкторы в таком классе должны быть public или protected, а методы, возвращающие bean, должны быть отмечены аннотацией @Bean.
@RequestMapping используется для мапинга (связывания) с URL для всего класса или для конкретного метода обработчика.
Чем отличаются аннотации @Bean и @Component?
Аннотация @Component (как и @Service и @Repository) используется для автоматического обнаружения и автоматической настройки бинов в ходе сканирования путей к классам.
@Component используется для аннотирования классов, которые должны быть автоматически обнаружены и зарегистрированы в контексте Spring. Эта аннотация может быть использована для любого компонента, такого как сервисы, репозитории, контроллеры и т.д.
@Bean используется для методов, которые должны быть вызваны для создания и инициализации объектов в контексте Spring. Эта аннотация может использоваться в классах, помеченных аннотацией @Configuration, и методы, помеченные этой аннотацией, будут вызываться для создания бинов.
Аннотация @Bean используется для явного объявления бина и позволяет добавить bean, уже реализованного сторонней библиотекой.
Аннотация @Bean используется для явного объявления бина, а не для того, чтобы Spring делал это автоматически в ходе сканирования путей к классам:
Таким образом, основное отличие между @Bean и @Component заключается в том, что первая используется для создания и настройки объектов в контексте Spring, а вторая для обнаружения и регистрации компонентов в контексте Spring.
Расскажите про аннотации @Service и @Repository. Чем они отличаются?
Аннотация @Service и @Repository являются специализированными версиями аннотации @Component в Spring Framework, и каждая из них предназначена для использования в конкретных слоях приложения.
Аннотация @Repository предназначена для классов, которые предоставляют доступ к базе данных или другим источникам данных, таким как файловые системы или JMS-очереди. Эта аннотация обычно используется в слое доступа к данным (DAO).
Задача @Repository заключается в том, чтобы отлавливать определенные исключения персистентности и пробрасывать их как одно непроверенное исключение Spring Framework. Для этого в контекст должен быть добавлен класс PersistenceExceptionTranslationPostProcessor.
Мы помечаем бины аннотацией @Service, чтобы указать, что они содержат бизнес- логику. Так что нет никакого другого предназначения, кроме как использовать ее на уровне сервиса.
Аннотация @Service предназначена для классов, которые предоставляют бизнес-логику приложения, такую как обработка данных и выполнение операций над ними. Эта аннотация обычно используется в сервисном слое приложения.
Расскажите про аннотацию @Autowired
Аннотация @Autowired в Spring Framework используется для автоматической внедрения зависимостей в поля классов, методы или конструкторы.
Она позволяет автоматически связывать бины (объекты) между собой,
Это означает, что Spring Framework автоматически находит классы, которые удовлетворяют зависимости, объявленные в вашем классе, и создает экземпляры этих классов, которые можно использовать.
Это аннотация Spring Framework, ею помечают конструктор, поле, сеттер-метод или метод конфигурации, сигнализируя, что им обязательно требуется внедрение зависимостей.
@Autowired – автоматическое внедрение подходящего бина:
При циклической зависимости, когда объекты ссылаются друг на друга, нельзя ставить над конструктором.
Начиная со 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; }Основные правила использования аннотации @Autowired в Spring Framework:
Основные правила использования аннотации @Autowired в Spring Framework:
Расскажите про аннотацию @Qualifier
@Qualifier - это аннотация в Spring Framework, которая используется для разрешения конфликтов при инъекции зависимостей.
Когда в приложении есть несколько бинов (компонентов), которые соответствуют типу и классу, то Spring не может определить, какой из них должен быть использован в конкретном месте, где происходит инъекция зависимости. В этом случае @Qualifier позволяет явно указать, какой именно бин должен быть использован.
Пример использования @Qualifier:
@Service
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;
// ...
}В этом примере мы явно указываем, что для инъекции зависимости UserRepository необходимо использовать бин с именем “userRepositoryImpl”. Без использования @Qualifier Spring не смог бы определить, какой именно бин использовать, если в приложении существует несколько классов, реализующих интерфейс UserRepository.
Расскажите про аннотацию @Value
Аннотация @Value - это аннотация в Spring Framework, которая используется для инъекции значения свойства из внешнего источника в Spring-управляемый компонент.
@Autowired и @Value могут использоваться вместе, чтобы инъектировать значения свойств в Spring-управляемые компоненты, используя имена свойств, которые указываются в @Value.
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Value("${my.property}")
private String myProperty;
// ...
}В этом примере мы использовали @Autowired для инъекции MyRepository в поле myRepository класса MyService, а также использовали @Value для инъекции значения свойства my.property в поле myProperty класса MyService. Значение my.property должно быть определено внутри внешнего источника, такого как application.properties или application.yml.
Расскажите про аннотацию @Resource
Java-аннотация @Resource может применяться к классам, полям и методам. Она пытается получить зависимость: сначала по имени, затем по типу, затем по описанию (Qualifier).
Имя извлекается из имени аннотируемого сеттера или поля, либо берется из параметра name.
При аннотировании классов имя не извлекается из имени класса по умолчанию, поэтому оно должно быть указано явно.
Аннотация @Resource является альтернативой аннотации @Autowired в Spring и имеет несколько отличий:
Аннотация @Named
Аннотация @Named является частью JSR 330 (Dependency Injection for Java), которая используется для указания имени для определенного компонента или бина, который может быть использован в DI контейнере.
@Named является альтернативой аннотации @Component, которая является частью Spring Framework. Она используется для маркировки классов, которые будут создаваться и управляться контейнером Spring.
В отличие от @Component, которая создает бин с именем класса, @Named позволяет указать произвольное имя для создаваемого бина. Это позволяет избежать конфликтов имен при создании бинов и облегчает конфигурирование DI контейнера.
@Inject
@Named("userService")
private UserService userService;В этом примере мы использовали аннотацию @Inject, которая является частью JSR 330, для внедрения зависимости UserService в наш класс. Мы также использовали @Named для указания имени “userService” для UserService.
Расскажите про аннотацию @Inject
@Inject (аннотация java) – аналог @Autowired (аннотация spring) в первую очередь пытается подключить зависимость по типу, затем по описанию и только потом по имени.
Также стоит отметить, что аннотация @Inject похожа на аннотацию @Autowired в Spring Framework. Однако, в отличие от @Autowired, аннотация @Inject является частью стандарта Java EE и может использоваться в любом контейнере, который поддерживает JSR-330.
Аналог @Autowired - пытается получить зависимость в таком порядке:
1) По типу
2) По описанию
3) По имени
В ней нет параметров, поэтому при использовании бина по Id, используем
@Named
@Inject
@Named("someName")
private method1()Расскажите про аннотацию @Lookup
Аннотация @Lookup в Spring Framework используется для внедрения зависимостей с динамическим созданием объектов. Это позволяет создавать новые экземпляры бинов на лету, вместо того, чтобы внедрять один и тот же экземпляр бина в каждый класс, который его требует.
В основе работы аннотации @Lookup лежит использование прокси-объекта, который создается Spring Framework для класса, помеченного этой аннотацией. Когда вызывается метод, помеченный @Lookup, Spring Framework перехватывает вызов и создает новый экземпляр бина на лету.
@Component
public class Car {
@Lookup
public Passenger getPassenger() {
// This method will be overridden by Spring
// and return a new instance of Passenger every time it's called
return null;
}
public void drive() {
Passenger passenger = getPassenger();
// Use the new instance of Passenger
// ...
}
}
@Component
@Scope("prototype")
public class Passenger {
// ...
}Аннотация @Lookup в Spring Framework используется для внедрения зависимостей через “look-up” методы. Эти методы определяются в интерфейсах или абстрактных классах, а их конкретная реализация генерируется Spring’ом во время выполнения.
Например, допустим у нас есть интерфейс UserService, который определяет методы для работы с пользователями. В этом интерфейсе мы можем объявить метод getUser, помеченный аннотацией @Lookup, который будет возвращать новый экземпляр User каждый раз, когда он вызывается.
public interface UserService {
@Lookup
public User getUser();
}Затем мы можем создать конкретную реализацию этого интерфейса, помеченную аннотацией @Service:
@Service
public class UserServiceImpl implements UserService {
public User getUser() {
return new User();
}
}При каждом вызове метода getUser() будет создаваться новый экземпляр User. Это может быть полезно в некоторых случаях, например, когда необходимо создавать новый объект для каждого запроса или когда объекты должны быть уникальными для каждого потока выполнения.
Аннотация @Lookup позволяет решать несколько задач и преодолевать некоторые проблемы:
Однако, при использовании @Lookup также есть некоторые проблемы:
Можно ли вставить бин в статическое поле? Почему?
Spring не позволяет внедрять бины напрямую в статические поля. Это связано с тем, что когда загрузчик классов загружает статические значения, контекст Spring еще не загружен.
Если мы попытаемся вставить бин напрямую в статическое поле, как это было описано в предыдущем ответе, то контейнер Spring не сможет управлять этим бином, потому что в момент загрузки класса контекст Spring еще не загружен.
Чтобы исправить это, можно создать нестатический сеттер-метод с @Autowired:
private static OrderItemService orderItemService;
@Autowired
public void setOrderItemService(OrderItemService orderItemService) {
TestDataInit.orderItemService = orderItemService;
}Расскажите про аннотации @Primary и @Qualifier
@Qualifier применяется, если кандидатов для автоматического связывания несколько, аннотация позволяет указать в качестве аргумента имя конкретного бина, который следует внедрить.
Она может быть применена к отдельному полю класса, к отдельному аргументу метода или конструктора
Аннотация @Qualifier позволяет явно указать, какой именно бин нужно внедрить в зависимость. Это полезно в том случае, если у нас есть несколько бинов с одним и тем же типом и необходимо выбрать определенный бин для внедрения в зависимость.
@Primary тоже используется, чтобы отдавать предпочтение бину, когда есть несколько бинов одного типа, но в ней нельзя задать имя бина, она определяет значение по умолчанию.
Аннотация @Primary используется для пометки бина, который будет использоваться по умолчанию в случае, если есть несколько кандидатов на внедрение зависимости одного типа. Например, если у нас есть два бина с одним и тем же типом, то Spring будет использовать тот, который помечен аннотацией @Primary.
при использовании как аннотации @Primary, так и @Qualifier, приоритет будет у @Qualifier. Таким образом, если присутствуют обе аннотации, то Sprin
Например, если есть два бина типа UserService, один помечен аннотацией @Primary, а второй помечен аннотацией @Qualifier(“adminUserService”), то при запросе бина UserService Spring выберет бин с аннотацией @Primary, несмотря на наличие аннотации @Qualifier.
Как заинжектить примитив?
Внедрить в поле примитив можно с помощью аннотации @Value на уровне параметров поля или конструктора/метода.
Нам понадобится файл свойств (*.properties), чтобы определить значения, которые мы хотим внедрить аннотацией @Value. Сначала в нашем классе конфигурации нам нужно указать аннотацию @PropertySource с именем файла свойств.
@Component
public class MyComponent {
@Value("10")
private int myInt;@Value(“${some.key}”)
public String stringWithDefaultValue;В эту переменную будет внедрена строка, например, из property или из view.
Кроме того, для внедрения значений можно использовать язык SpEL (Spring Expression Language(
С помощью SpEL можно выполнить арифметические операции, сравнения и логические операции над значениями.
SpEL поддерживает использование переменных, функций и операторов для создания более сложных выражений.).
@Autowired
public MyComponent(@Value("${my.property}") String value) {
this.value = value;
}Как заинжектить коллекцию?
Если внедряемый объект массив, коллекция или map с дженериком, то, используя аннотацию @Autowired, Spring внедрит все бины, подходящие по типу в этот массив (или другую структуру данных). В случае с map ключом будет имя бина.
Используя аннотацию @Qualifier можно настроить тип искомого бина.
Использование аннотации @Inject:
Использование аннотации @Resource:
можно собрать все бины одного типа(например все имплементации какого-либо интерфейса), находящиеся в контейнере, и внедрить их в коллекцию или массив, используя аннотацию @Autowired с квалификатором @Qualifier, указывающим на нужный тип бина. Например, чтобы собрать все бины типа MyBean в список, можно сделать следующее:
@Autowired
@Qualifier("myBean")
private List<MyBean> myBeans;Бины могут быть упорядочены, если вставляются в списки (не Set или Map) или массивы. Поддерживаются как аннотация @Order, так и интерфейс Ordered.
Расскажите про аннотацию @Conditional
Аннотация @Conditional позволяет определить условия, которые необходимо учитывать при создании бинов и конфигураций в Spring. Если условие выполняется, то бин или конфигурация будет создана, в противном случае - нет.
Для определения условий необходимо создать классы, реализующие интерфейс Condition, и переопределить его метод matches(). В этом методе можно прописать любую логику проверки условий.
Например, можно проверять наличие определенного свойства в системе, наличие определенного бина в контексте и т.д.
Класс, помеченный аннотацией @Configuration, может быть также помечен и аннотацией @Conditional. В этом случае, все методы, помеченные аннотациями @Bean, @Import и @ComponentScan, будут создаваться только в том случае, если условие, указанное в аннотации @Conditional, выполняется.
Таким образом, использование аннотации @Conditional позволяет гибко настраивать создание бинов и конфигураций в Spring, в зависимости от различных условий.
@Configuration
public class AppConfig {
@Bean(name = "myBean")
@Conditional(MyCondition.class)
public MyBean myBean() {
return new MyBean();
}
}
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// Здесь можно реализовать логику проверки условия.
// Например, проверка наличия системного свойства с именем "my.property"
return System.getProperty("my.property") != null;
}
}
public class MyBean {
// Код бина
}В данном примере, при запуске приложения, перед созданием бина “myBean”, будет вызван метод matches() класса MyCondition, где можно проверить выполнение нужного условия. Если условие выполнено, то бин будет создан, иначе - нет.
Класс MyCondition реализует интерфейс Condition и переопределяет его метод matches(). В данном примере, условие проверяет наличие системного свойства с именем “my.property”. Если такое свойство существует, то условие считается выполненным, и бин будет создан. Если свойство не существует, то бин не будет создан.
Расскажите про аннотацию @ComponentScan
Используется для указания пакетов, которые мы хотим сканировать на наличие компонентов, из которых нужно сделать бины.
Используется вместе с аннотацией @Configuration.
@ComponentScan без аргументов указывает Spring по умолчанию сканировать текущий пакет и все его подпакеты. Текущий пакет - тот, в котором находится файл конфигурации с этой самой аннотацией @ComponentScan. В данном случае в контейнер попадут:
* бин конфигурационного класса;
* бины, объявленные в конфигурационном классе с помощью @Bean;
* все бины из пакета и его подпакетов.
Аннотация @SpringBootApplication включает в себя аннотации @ComponentScan, @SpringBootConfiguration и @EnableAutoConfiguration, но это не мешает разместить её ещё раз отдельно для указания конкретного пакета.
Если указать с атрибутом exludeFilters, то это позволит использовать фильтр и исключать ненужные классы из процесса сканирования.