Сообщения

Сообщения за июль, 2020

Spring IoC контейнер: Java конфигурация, @Bean и @Configuration

Изображение
Центральными артефактами поддержки Java-конфигурации Spring с использованием new являются @Configuration-аннотированные классы и @Bean-аннотированные методы. Аннотация @Bean используется для указания того, что метод создает, настраивает и инициализирует новый объект, который будет управляться контейнером Spring IoC. Для сравнения с XML-конфигурацией Spring <beans/>, аннотация @Bean играет ту же роль, что и элемент <bean/>. Вы можете использовать аннотированные @Bean методы с любым Spring @Component. Однако они чаще всего используются с bean-компонентами @Configuration. Аннотирование класса с помощью @Configuration указывает на то, что его основное назначение - источник определений бина. Кроме того, классы @Configuration позволяют определять зависимости между компонентами, вызывая другие методы @Bean в том же классе. Простейший из возможных классов @Configuration выглядит следующим образом: Java @Configuration public class AppConfig { @Bean public MyService m

Spring IoC контейнер: ограничения стандартных аннотаций JSR 330

Изображение
При работе со стандартными аннотациями вы должны знать, что некоторые важные функции недоступны, как показано в следующей таблице: Spring javax.inject.* javax.inject ограничения/комментарии @Autowired @Inject @Inject не имеет атрибута 'required'. Вместо этого может использоваться с Optional Java 8. @Component @Named / @ManagedBean JSR-330 не предоставляет составную модель, только способ идентифицировать именованные компоненты. @Scope("singleton") @Singleton Область действия JSR-330 по умолчанию похожа на прототип (prototype) в Spring. Тем не менее, чтобы поддерживать его в соответствии с общими значениями по умолчанию Spring, bean-компонент JSR-330, объявленный в контейнере Spring, по умолчанию является одноэлементным (singleton). Чтобы использовать область, отличную от singleton, вы должны использовать аннотацию Spring @Scope. javax.inject также предоставляет аннотацию @Scope. Тем не менее, она предназначена только для создания ваших собственных

Spring IoC контейнер: аннотации JSR 330, @Named и @ManagedBean - стандартные эквиваленты аннотации @Component

Изображение
Вместо @Component вы можете использовать @javax.inject.Named или javax.annotation.ManagedBean, как показано в следующем примере: Java import javax.inject.Inject; import javax.inject.Named; // @ManagedBean("movieListener") также может быть использован @Named("movieListener") public class SimpleMovieLister { private MovieFinder movieFinder; @Inject public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // ... } Kotlin import javax.inject.Inject import javax.inject.Named // @ManagedBean("movieListener") также может быть использован @Named("movieListener") class SimpleMovieLister { @Inject lateinit var movieFinder: MovieFinder // ... } Очень часто используется @Component без указания имени для компонента. @Named можно использовать аналогичным образом, как показано в следующем примере: Java import javax.inject.Inject; import javax.inject.Named; @Na

Spring IoC контейнер: использование стандартных аннотаций JSR 330, внедрение зависимостей с @Inject и @Named

Изображение
Начиная со Spring 3.0, Spring предлагает поддержку стандартных аннотаций JSR-330 (Dependency Injection). Эти аннотации сканируются так же, как аннотации Spring. Чтобы использовать их, вы должны иметь соответствующие jar в вашем classpath. Если вы используете Maven, артефакт javax.inject доступен в стандартном репозитории Maven (https://repo1.maven.org/maven2/javax/inject/javax.inject/1/). Вы можете добавить следующую зависимость в ваш файл pom.xml: <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> Внедрение зависимостей с @Inject и @Named Вместо @Autowired вы можете использовать @javax.inject.Inject следующим образом: Java import javax.inject.Inject; public class SimpleMovieLister { private MovieFinder movieFinder; @Inject public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } publi

Spring IoC контейнер: сканирование classpath, генерация индекса компонентов-кандидатов

Изображение
Хотя сканирование пути к классам очень быстрое, можно улучшить производительность запуска больших приложений, создав статический список кандидатов во время компиляции. В этом режиме все модули, которые являются целью сканирования компонентов, должны использовать этот механизм. Ваши существующие директивы @ComponentScan или <context:component-scan должны оставаться без изменений, чтобы запрашивать контекст для сканирования кандидатов в определенных пакетах. Когда ApplicationContext обнаруживает такой индекс, он автоматически использует его, а не сканирует путь к классам. Чтобы создать индекс, добавьте дополнительную зависимость к каждому модулю, который содержит компоненты, которые являются целями для директив сканирования компонентов. В следующем примере показано, как это сделать с Maven: <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-indexer</artifactId> <version&

Spring IoC контейнер: сканирование classpath, предоставление метаданных квалификатора с аннотациями

Изображение
Аннотация @Qualifier обсуждалась в посте " Настройка автопривязки на основе аннотаций с @Qualifier ". Примеры в том посте демонстрируют использование аннотации @Qualifier и пользовательских аннотаций квалификатора для обеспечения детального контроля при разрешении кандидатов с автопривязкой. Поскольку те примеры были основаны на определениях bean-компонентов XML, метаданные квалификатора были предоставлены в определениях bean-кандидатов с использованием квалификатора или мета-дочерних элементов элемента bean-компонента в XML. Полагаясь на сканирование пути к классам для автоматического обнаружения компонентов, вы можете предоставить метаданные квалификатора с аннотациями на уровне типа для класса-кандидата. Следующие три примера демонстрируют эту технику: Java @Component @Qualifier("Action") public class ActionMovieCatalog implements MovieCatalog { // ... } Kotlin @Component @Qualifier("Action") class ActionMovieCatalog : MovieCatalog J

Spring IoC контейнер: сканирование classpath, предоставление области действия для автоопределенных компонентов

Изображение
Как и в случае с компонентами, управляемыми Spring в целом, по умолчанию и наиболее распространенной областью действия для автоматически обнаруживаемых компонентов является singleton. Однако иногда вам нужна другая область, которая может быть указана в аннотации @Scope. Вы можете указать имя области в аннотации, как показано в следующем примере: Java @Scope("prototype") @Repository public class MovieFinderImpl implements MovieFinder { // ... } Kotlin @Scope("prototype") @Repository class MovieFinderImpl : MovieFinder { // ... } Аннотации @Scope используются только для конкретного класса компонентов (для аннотированных компонентов) или для фабричного метода (для методов @Bean). В отличие от определений bean-компонентов XML, понятие наследования определений bean отсутствует, и иерархии наследования на уровне класса не имеют значения для целей метаданных. Как и в случае с предварительно созданными аннотациями для областей, вы также можете создав

Spring IoC контейнер: сканирование classpath, именование автоопределенных компонентов

Изображение
Когда компонент автоматически определяется как часть процесса сканирования, его имя компонента создается стратегией BeanNameGenerator, известной этому сканеру. По умолчанию любая стереотипная аннотация Spring (@Component, @Repository, @Service и @Controller), которая содержит значение имени, тем самым предоставляет это имя соответствующему определению компонента. Если такая аннотация не содержит значения имени или какого-либо другого обнаруженного компонента (например, обнаруженного с помощью пользовательских фильтров), генератор имен компонентов по умолчанию возвращает некапитализированное неквалифицированное имя класса. Например, если были обнаружены следующие классы компонентов, имена будут myMovieLister и movieFinderImpl: Java @Service("myMovieLister") public class SimpleMovieLister { // ... } Kotlin @Service("myMovieLister") class SimpleMovieLister { // ... } Java @Repository public class MovieFinderImpl implements MovieFinder {

Spring IoC контейнер: сканирование classpath, определение метаданных компонента в компонентах

Изображение
Компоненты Spring также могут предоставлять метаданные определения компонента в контейнер. Это можно сделать с помощью той же аннотации @Bean, которая используется для определения метаданных bean-компонентов в аннотированных классах @Configuration. В следующем примере показано, как это сделать: Java @Component public class FactoryMethodComponent { @Bean @Qualifier("public") public TestBean publicInstance() { return new TestBean("publicInstance"); } public void doWork() { // Реализация метода компонента опущена } } Kotlin @Component class FactoryMethodComponent { @Bean @Qualifier("public") fun publicInstance() = TestBean("publicInstance") fun doWork() { // Реализация метода компонента опущена } } Предыдущий класс является компонентом Spring, который имеет специфичный для приложения код в своем методе doWork(). Однако он также вносит определение bean-компонента,

Spring IoC контейнер: сканирование classpath, использование фильтров для настройки сканирования

Изображение
По умолчанию классы, аннотированные @Component, @Repository, @Service, @Controller, @Configuration или пользовательские аннотации, которые сами аннотируются @Component, являются единственными обнаруженными компонентами-кандидатами. Однако вы можете изменить и расширить это поведение, применяя пользовательские фильтры. Добавьте их как атрибуты includeFilters или excludeFilters аннотации @ComponentScan (или как дочерние элементы <context:include-filter /> или <context:exclude-filter /> элемента <context:component-scan> в конфигурации XML). Каждый элемент фильтра требует атрибутов типа и выражения. В следующей таблице описаны параметры фильтрации: Тип фильтра Пример выражения Описание annotation (default) org.example.SomeAnnotation Аннотация, которая должна присутствовать или мета-присутствовать на уровне типа в целевых компонентах. assignable org.example.SomeClass Класс (или интерфейс), которому целевые компоненты могут быть назначены (расширены или реал

Spring IoC контейнер: сканирование classpath, автоматическое определение классов и регистрация определений бинов

Изображение
Spring может автоматически обнаруживать стереотипные классы и регистрировать соответствующие экземпляры BeanDefinition с помощью ApplicationContext. Например, следующие два класса имеют право на такое автоопределение: Java @Service public class SimpleMovieLister { private MovieFinder movieFinder; public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } } Kotlin @Service class SimpleMovieLister(private val movieFinder: MovieFinder) Java @Repository public class JpaMovieFinder implements MovieFinder { // реализация исключена для ясности } Kotlin @Repository class JpaMovieFinder : MovieFinder { // реализация исключена для ясности } Для автоматического определения этих классов и регистрации соответствующих bean-компонентов вам необходимо добавить @ComponentScan в ваш класс @Configuration, где атрибут basePackages является общим родительским пакетом для этих двух классов. (В качестве альтернативы вы мож

Spring IoC контейнер: сканирование classpath, использование метааннотаций и составных аннотаций

Изображение
Многие из аннотаций, предоставляемых Spring, могут использоваться как метааннотации в вашем собственном коде. Метааннотация - это аннотация, которая может быть применена к другой аннотации. Например, упомянутая ранее аннотация @Service мета-аннотирована с помощью @Component, как показано в следующем примере: Java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component // Component заставляет @Service обрабатываться так же, как @Component. public @interface Service { // ... } Kotlin @Target(AnnotationTarget.TYPE) @Retention(AnnotationRetention.RUNTIME) @MustBeDocumented @Component // Component заставляет @Service обрабатываться так же, как @Component. annotation class Service { // ... } Вы также можете комбинировать метааннотации для создания "составных аннотаций". Например, аннотация @RestController из Spring MVC состоит из @Controller и @ResponseBody. Кроме того, составные аннотации могут по желанию повторно объявлять

Spring IoC контейнер: сканирование classpath, @Component и дополнительные стереотипные аннотации

Изображение
Аннотация @Repository является маркером для любого класса, который выполняет роль или стереотип репозитория (также известный как объект доступа к данным (Data Access Object) или DAO). Среди применений этого маркера - автоматический перевод исключений. Spring предоставляет дополнительные стереотипные аннотации: @Component, @Service и @Controller. @Component - это общий стереотип для любого компонента, управляемого Spring. @Repository, @Service и @Controller являются специализациями @Component для более конкретных случаев использования (соответственно, в слоях постоянства (persistence), обслуживания (service) и представления (presentation)). Следовательно, вы можете аннотировать свои классы компонентов с помощью @Component, но, вместо этого, аннотируя их с помощью @Repository, @Service или @Controller, ваши классы лучше подходят для обработки инструментами или связи с аспектами. @Repository, @Service и @Controller могут содержать дополнительную семантику в будущих версиях Spring Framewo

Spring IoC контейнер: сканирование Classpath и управляемые компоненты

Изображение
В большинстве примеров в постах Spring IoC контейнер XML используется для указания метаданных конфигурации, которые создают каждое BeanDefinition в контейнере Spring. Предыдущие посты (Конфигурация контейнера на основе аннотаций) демонстрируют, как предоставить множество метаданных конфигурации с помощью аннотаций на уровне кода. Однако даже в этих примерах определения "базовых" bean-компонентов явно определены в файле XML, тогда как аннотации управляют только внедрением зависимостей. В последующих постах Сканирование classpath описывается опция для неявного обнаружения компонентов-кандидатов путем сканирования пути к классам. Компоненты-кандидаты - это классы, которые соответствуют критериям фильтра и имеют соответствующее определение компонента, зарегистрированное в контейнере. Это устраняет необходимость использования XML для регистрации бина. Вместо этого вы можете использовать аннотации (например, @Component), выражения типа AspectJ или ваши собственные критерии фильтрац

Spring IoC контейнер: конфигурация на основе аннотаций, @PostConstruct и @PreDestroy

Изображение
CommonAnnotationBeanPostProcessor распознает не только аннотацию @Resource, но и аннотации жизненного цикла JSR-250: javax.annotation.PostConstruct и javax.annotation.PreDestroy. Представленная Spring 2.5, поддержка этих аннотаций предлагает альтернативу механизму обратного вызова жизненного цикла, описанному в обратных вызовах инициализации и обратных вызовах уничтожения . При условии, что CommonAnnotationBeanPostProcessor зарегистрирован в Spring ApplicationContext, метод, содержащий одну из этих аннотаций, вызывается в той же точке жизненного цикла, что и соответствующий метод интерфейса жизненного цикла Spring или явно объявленный метод обратного вызова. В следующем примере кэш предварительно заполняется при инициализации и очищается при уничтожении: Java public class CachingMovieLister { @PostConstruct public void populateMovieCache() { // заполняет кэш фильма при инициализации... } @PreDestroy public void clearMovieCache() { // очищает

Spring IoC контейнер: конфигурация на основе аннотаций, @Value

Изображение
@Value обычно используется для внедрения внешних свойств: Java @Component public class MovieRecommender { private final String catalog; public MovieRecommender(@Value("${catalog.name}") String catalog) { this.catalog = catalog; } } Kotlin @Component class MovieRecommender(@Value("\${catalog.name}") private val catalog: String) Со следующей конфигурацией: Java @Configuration @PropertySource("classpath:application.properties") public class AppConfig { } Kotlin @Configuration @PropertySource("classpath:application.properties") class AppConfig И следующий файл application.properties: catalog.name=MovieCatalog В этом случае параметр и поле каталога будут равны значению MovieCatalog. Spring предоставляет встроенный преобразователь значений снисхождения. Он будет пытаться разрешить значение свойства, и, если оно не может быть разрешено, имя свойства (например, ${catalog.name}) будет введено в

Spring IoC контейнер: конфигурация на основе аннотаций, @Resource

Изображение
Spring также поддерживает внедрение с помощью аннотации JSR-250 @Resource (javax.annotation.Resource) для полей или методов установки свойств бина. Это общий шаблон в Java EE: например, в управляемых JSF bean-компонентах и конечных точках JAX-WS. Spring поддерживает этот шаблон и для объектов, управляемых Spring. @Resource принимает атрибут name. По умолчанию Spring интерпретирует это значение как имя bean-компонента для внедрения. Другими словами, это следует за семантикой имени, как продемонстрировано в следующем примере: Java public class SimpleMovieLister { private MovieFinder movieFinder; @Resource(name="myMovieFinder") public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } } Kotlin class SimpleMovieLister { @Resource(name="myMovieFinder") private lateinit var movieFinder:MovieFinder } Если имя не указано явно, имя по умолчанию выводится из имени поля или метода установки.

Spring IoC контейнер: конфигурация на основе аннотаций, использование CustomAutowireConfigurer

Изображение
CustomAutowireConfigurer - это BeanFactoryPostProcessor, который позволяет регистрировать собственные типы аннотаций квалификаторов, даже если они не аннотированы аннотацией Spring @Qualifier. В следующем примере показано, как использовать CustomAutowireConfigurer: <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"> <property name="customQualifierTypes"> <set> <value>example.CustomQualifier</value> </set> </property> </bean> AutowireCandidateResolver определяет кандидатов для автоматической привязки по: Значение autowire-candidate каждого определения бина Любые шаблоны default-autowire-candidates, доступные в элементе <beans/> Наличие аннотаций @Qualifier и любых пользовательских аннотаций, зарегистрированных в CustomAutowireConfigurer Когда несколько bean-компонентов квалифицируются к

Spring IoC контейнер: конфигурация на основе аннотаций, использование дженериков в качестве квалификаторов автопривязки

Изображение
В дополнение к аннотации @Qualifier вы можете использовать универсальные типы Java (дженерики) в качестве неявной формы квалификации. Например, предположим, что у вас есть следующая конфигурация: Java @Configuration public class MyConfiguration { @Bean public StringStore stringStore() { return new StringStore(); } @Bean public IntegerStore integerStore() { return new IntegerStore(); } } Kotlin @Configuration class MyConfiguration { @Bean fun stringStore() = StringStore() @Bean fun integerStore() = IntegerStore() } Предполагая, что предыдущие компоненты реализуют универсальный интерфейс (то есть Store<String> и Store<Integer>), вы можете привязать с помощью @Autowire интерфейс Store, и дженерик используется в качестве квалификатора, как показано в следующем примере: Java @Autowired private Store<String> s1; // <String> qualifier, внедряет stringStore bean @Autowired private Store&l

Spring IoC контейнер: конфигурация на основе аннотаций, настройка автопривязки на основе аннотаций с @Qualifier

Изображение
@Primary - эффективный способ использовать автоматическую привязку по типу с несколькими случаями, когда можно определить одного основного кандидата. Когда вам нужно больше контроля над процессом выбора, вы можете использовать аннотацию Spring @Qualifier . Вы можете связать значения квалификатора с конкретными аргументами, сузив набор совпадений типов, чтобы для каждого аргумента был выбран конкретный компонент. В простейшем случае это может быть просто описательное значение, как показано в следующем примере: Java public class MovieRecommender { @Autowired @Qualifier("main") private MovieCatalog movieCatalog; // ... } Kotlin class MovieRecommender { @Autowired @Qualifier("main") private lateinit var movieCatalog: MovieCatalog // ... } Вы также можете указать аннотацию @Qualifier для отдельных аргументов конструктора или параметров метода, как показано в следующем примере: Java public class MovieRecommender {