Аннотация @Profile
в Spring может использоваться для любых компонентов Spring (например, @Component
, @Service
, @Configuration
и т. Д.), @Configuration
являются кандидатами для автоматического обнаружения. Аннотация @Profile
принимает один профиль или набор профилей, которые должны быть активными, чтобы аннотированный компонент имел право на автоопределение. Для данного @Profile({"p1", "!p2"})
регистрация произойдет, если профиль p1
активен или если профиль p2
не активен. Здесь или имеет решающее значение.
Но как этого добиться с помощью @Profile
: мы хотим активировать данный компонент, если профиль p1
активен и профили p2
и p3
оба неактивны?
Давайте предположим следующую ситуацию: у нас есть интерфейс NotificationSender
который реализуется с помощью:
-
SendGridNotificationSender
— активен, только еслиsendgrid
профильsendgrid
, -
EmailNotificationSender
— активен, только если активен профильemail
. -
NoOpNotificationSender
— активен, только если активен профильdevelopment
и ни один изsendgrid
иemail
не активен
Кроме того: одновременно может быть зарегистрирован только один NotificationSender
а профиль development
может использоваться вместе с sendgrid
и email
.
В описанной выше ситуации использование аннотации @Profile
кажется недостаточно. Может быть, я немного усложняю вещи, но на самом деле я действительно хотел достичь вышеизложенного, не вводя другой профиль. И как я это сделал?
Я использовал аннотацию Spring 4 @Conditional
. @Conditional
разрешить регистрацию компонента, когда все указанные Condition
соответствуют:
1
2
3
4
5
|
@Component @Conditional (value = NoOpNotificationSender.ProfilesCondition. class ) class NoOpNotificationSender extends NotificationSenderAdapter { } |
ProfilesCondition
реализует интерфейс org.springframework.context.annotation.Condition
:
1
2
3
4
5
6
|
public static class ProfilesCondition implements Condition { @Override public boolean matches(ConditionContext c, AnnotatedTypeMetadata m) { } } |
Целое решение проблемы:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@Component @Conditional (value = NoOpNotificationSender.ProfilesCondition. class ) class NoOpNotificationSender extends NotificationSenderAdapter { static class ProfilesCondition implements Condition { @Override public boolean matches(ConditionContext c, AnnotatedTypeMetadata m) { return accepts(c, Profiles.DEVELOPMENT) && !accepts(c, Profiles.MAIL) && !accepts(c, Profiles.SEND_GRID); } private boolean accepts(ConditionContext c, String profile) { return c.getEnvironment().acceptsProfiles(profile); } } } |
Другие компоненты будут активированы, когда соответствующий профиль активен:
01
02
03
04
05
06
07
08
09
10
11
|
@Component @Profile (value = Profiles.SEND_GRID) public class SendGridNotificationSender extends NotificationSenderAdapter { } @Component @Profile (value = Profiles.MAIL) class EmailNotificationSender extends NotificationSenderAdapter { } |
Примеры использования:
Активные профили | боб |
---|---|
развитие | NoOpNotificationSender |
разработка, sendgrid | SendGridNotificationSender |
разработка, почта | EmailNotificationSender |
sendgrid | SendGridNotificationSender |
почта | EmailNotificationSender |
Что вы думаете? Как бы вы решили эту проблему?
Ссылка: | Как: зарегистрируйте компоненты, используя @Conditional и Condition in Spring, от нашего партнера по JCG Рафаля Боровца в блоге Codeleak.pl . |