Is it possible to configure a bean in such a way that it wont be used by a group of profiles? Currently I can do this (I believe):
@Profile("!dev, !qa, !local")
Is there a neater notation to achieve this? Let's assume I have lots of profiles. Also, if I have a Mock and concrete implementation of some service (or whatever), Can I just annotate one of them, and assume the other will be used in all other cases? In other words, is this, for example, necessary:
@Profile("dev, prof1, prof2") public class MockImp implements MyInterface {...} @Profile("!dev, !prof1, !prof2") //assume for argument sake that there are many other profiles public class RealImp implements MyInterface {...}
Could I just annotate one of them, and stick a @Primary
annotation on the other instead?
In essence I want this:
@Profile("!(dev, prof1, prof2)")
Thanks in advance!
You can exclude a bean from autowiring in Spring framework per-bean basis. If you are using Spring XML configuration then you can exclude a bean from autowiring by setting the autowire-candidate attribute of the <bean/> element to false.
Spring @Profile allow developers to register beans by condition. For example, register beans based on what operating system (Windows, *nix) your application is running, or load a database properties file based on the application running in development, test, staging or production environment.
The solution would be to create more property files and add the "profile" name as the suffix and configure Spring Boot to pick the appropriate properties based on the profile. Then, we need to create three application. properties : application-dev.
Since Spring 5.1 (incorporated in Spring Boot 2.1) it is possible to use a profile expression inside profile string annotation (see the description in Profile.of(..) for details).
So to exclude your bean from certain profiles you can use an expression like this:
@Profile("!dev & !prof1 & !prof2")
Other logical operators can be used as well, for example:
@Profile("test | local")
Short answer is: You can't in versions of Spring prior to Spring 5.1 (i.e. versions of Spring Boot prior to 2.1).
But there is a neat workarounds that exists thanks to the @Conditional
annotation.
public static abstract class ProfileCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { if (matchProfiles(conditionContext.getEnvironment())) { return ConditionOutcome.match("A local profile has been found."); } return ConditionOutcome.noMatch("No local profiles found."); } protected static abstract boolean matchProfiles(final Environment environment); } public class DevProfileCondition extends ProfileCondition { protected boolean matchProfiles(final Environment environment) { return Arrays.stream(environment.getActiveProfiles()).anyMatch(prof -> { return prof.equals("dev") || prof.equals("prof1") || prof.equals("prof2"); }); } } public static class ProdProfileCondition extends ProfileCondition { protected boolean matchProfiles(final Environment environment) { return Arrays.stream(environment.getActiveProfiles()).anyMatch(prof -> { return (!prof.equals("dev") && !prof.equals("prof1") && !prof.equals("prof2")); }); } }
@Conditional(value = {DevProfileCondition.class}) public class MockImpl implements MyInterface {...} @Conditional(value = {ProdProfileCondition.class}) public class RealImp implements MyInterface {...}
However, this aproach requires Springboot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With