Update:
When we have to decide before context creation (.i.e. ApplicationListener is no Component/Bean), then we (just mimic profiles) set:
# env: SET MY_FLAG=foo -> System.getenv("MY_FLAG")
# system: java -jar -Dmy.flag=foo myApp.jar -> System.getProperty("my.flag")
# cmd arg:
java -jar myApp.jar aws
..and issue it in our (spring boot) main method like:
if("aws".equalsIgnoreCase(args[0])) // alternatively: System.get...
application.addListeners(new DatabasePropertiesListener());
Misunderstood answer
Sure we can: With spring (boot) core features!
Assuming our ApplicationListener is a "spring managed bean", we annotate it with:
@Component
@Profile("aws") // custom profile (name)
class MyApplicationListener implements ...
{ ... }
...this will not load this "bean" into our context, unless we define:
spring.profiles.acitve=aws,... # a comma separated list of profiles to activate
Profiles
Spring Profiles provide a way to segregate parts of your application configuration and make it be available only in certain environments. Any @Component (Or @Bean,@Service,@Repository...descendants), @Configuration or @ConfigurationProperties can be marked with @Profile to limit when it is loaded, as shown in the ...
... above example.
An advanced application of @Profile annotation:
- with multiple profiles: "or"/"and" semantics
- "not" (
!) operator
@Profile("!local","aws") // (String[]: OR semantics) the annotated component/configuration/property will
// be loaded, when active profiles NOT contains "local" OR contains "aws"
// for AND semantics, we'd use (1 string): "!local & aws"
Activating Profile(s!)
spring.profiles.acitve can be set/added (like any spring property source) through several (14^^, precisely priorized) locations.
E.g. setting environment variable (5th lowest priority, but higher than application.properties (3rd lowest)):
SPRING_PROFILES_ACTIVE=aws
Or as a command line flag (when starting the application, 11th lowest/3rd highest priority):
java -jar myApp.jar --spring.profiles.active=aws,...
#comma separated list
For (spring) tests additionally exists an @ActiveProfiles annotation.
Remarks/Note
Deciding for profiles, we should ensure to "make it consistently" (not raising Nullpointer/BeaninitalizationExceptions ... with dependencies!;). If needed: Creating replacement/local/test (@Profile("!aws")) beans.
Activating a profile "xyz", automatically tries to load application-xyz.properties (with higher priority than application.properties (prio 3.1 - 3.4))...also in (spring-)cloud-config.
Not to forget: The default profile (activated by spring automatically, only when no explicit profile is activated).
Reference
For detailed documentation, please refer to:
Profile sample from Configuration Javadoc:
@Configuration classes may be marked with the @Profile annotation to indicate they should be processed only if a given profile or profiles are active:
@Profile("development")
@Configuration
public class EmbeddedDatabaseConfig {
@Bean
public DataSource dataSource() {
// instantiate, configure and return embedded DataSource
}
}
@Profile("production")
@Configuration
public class ProductionDatabaseConfig {
@Bean
public DataSource dataSource() {
// instantiate, configure and return production DataSource
}
}
Alternatively, you may also declare profile conditions at the @Bean method level — for example, for alternative bean variants within the same configuration class:
@Configuration
public class ProfileDatabaseConfig {
@Bean("dataSource")
@Profile("development")
public DataSource embeddedDatabase() { ... }
@Bean("dataSource")
@Profile("production")
public DataSource productionDatabase() { ... }
}
See the @Profile and Environment javadocs for further details.