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.