Spring предоставляет ряд аннотаций с именами, начинающимися с Enable * , по сути, эти аннотации позволяют активировать определенные управляемые функции Spring. Одним хорошим примером такой аннотации является EnableWebMvc, который включает все компоненты, необходимые для поддержки потока MVC в приложениях на основе Spring. Другим хорошим примером является аннотация EnableAsync для активации bean-компонентов для поддержки асинхронных функций в приложениях на основе Spring.
Мне было любопытно, как работают такие аннотации, и я хотел документировать свое понимание. Способ, которым эти аннотации поддерживаются, может считаться частью SPI и поэтому может нарушиться, если внутренняя реализация изменится в будущем.
Простое включение * Аннотации
Один из способов думать об этих пользовательских аннотациях состоит в том, что они добавляют набор новых bean-компонентов в контекст приложения Spring. Давайте начнем с определения одной такой пользовательской аннотации:
1
2
3
|
@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.TYPE) @interface EnableSomeBeans {} |
и примените эту аннотацию к классу Spring @Configuration:
1
2
3
|
@Configuration @EnableSomeBeans public static class SpringConfig {} |
Итак, теперь добавить набор bean-компонентов при применении этой аннотации так же просто, как добавить набор bean-компонентов для ввода с помощью аннотации @Import следующим образом:
1
2
3
4
|
@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.TYPE) @Import (SomeBeanConfiguration. class ) @interface EnableSomeBeans {} |
По сути, это так, если этот импортированный класс @Configuration определяет какие-либо компоненты, они теперь будут частью контекста приложения:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@Configuration class SomeBeanConfiguration { @Bean public String aBean1() { return "aBean1" ; } @Bean public String aBean2() { return "aBean2" ; } } |
Вот суть с рабочим образцом.
Включить * аннотации с помощью селекторов
Включить аннотации может быть гораздо сложнее, хотя они могут активировать другое семейство bean-компонентов в зависимости от их окружения. Примером такой аннотации является EnableCaching, который активирует конфигурацию на основе различных реализаций кэширования, доступных в пути к классам.
Написание таких аннотаций Enable * немного сложнее, чем простой пример ранее. Как и прежде, начните с пользовательской аннотации:
1
2
3
4
5
6
|
@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.TYPE) @Import (SomeBeanConfigurationSelector. class ) public @interface EnableSomeBeansSelector { String criteria() default "default" ; } |
Обратите внимание, что в этом случае пользовательская аннотация имеет образец поля, называемого критериями, и я хочу активировать два разных набора компонентов на основе этого критерия. Это может быть достигнуто с помощью селектора @Configuration, который может возвращать другой файл @Configuration в зависимости от контекста (в данном случае это значение поля критериев). Этот селектор имеет простую подпись, и это пример реализации:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
import org.springframework.context.annotation.ImportSelector; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; public class SomeBeanConfigurationSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( importingClassMetadata.getAnnotationAttributes (EnableSomeBeansSelector. class .getName(), false )); String criteria = attributes.getString( "criteria" ); if (criteria.equals( "default" )) { return new String[]{ "enableannot.selector.SomeBeanConfigurationDefault" }; } else { return new String[]{ "enableannot.selector.SomeBeanConfigurationType1" }; } } } @Configuration class SomeBeanConfigurationType1 { @Bean public String aBean() { return "Type1" ; } } @Configuration class SomeBeanConfigurationDefault { @Bean public String aBean() { return "Default" ; } } |
Таким образом, если поле критерия «default», бины в «SomeBeanConfigurationDefault» добавляются, в противном случае — в «SomeBeanConfigurationType1»
- Вот суть с рабочим образцом.
Вывод
Я надеюсь, что это дает понимание того, как Spring внутренне реализует аннотации @ Enable *, так как разработчик приложения может не нуждаться в создании таких аннотаций самостоятельно, более простым механизмом будет использование классов @Configuration и профилей bean-компонентов Spring для создания приложений.
Ссылка: | Spring Enable annotation — создание пользовательской аннотации Enable от нашего партнера JCG Биджу Кунджуммена в блоге all and sundry. |