Аннотация @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 . |