How the Spring @Profile annotation works

Spring profiles let developers configure their applications to behave differently in various environments.

Most Spring profile configurations occur in the application.properties (or YAML) file. However, with the @Profile annotation, developers can modify how dependency injection works in different environments, on various targets, and even during local testing.

The ability to switch an implementation class used during testing, as opposed to development or deployment, is particularly useful.

Spring @Profile annotation example

Consider a simple example of testing a number-guessing game. If the application generates a number randomly, testing would be unpredictable; however, random number generation is part of the requirements.

In this case, developers could create two Spring Beans: one generates a random number, and one for testing always returns the same value.

The random number generator is marked with a @Profile(“prod”) annotation, while the one that returns a constant value is marked with @Profile(“test”):

interface NumberGenerator {
  public int getNumber();
}

@Component
@Profile("prod")
class RandomNumberGenerator implements NumberGenerator {
  public int getNumber() {
    return (int)(Math.random() * 10);
  }
}

@Component
@Profile("dev")
class StaticNumberGenerator implements NumberGenerator {
  public int getNumber() {
    return 7;
  }
}

Setting the active Spring profile

Which number generator is used at runtime depends on how the active Spring profile is set.

spring.profiles.active=prod

This lets developers test their applications based on predictable results during development, while clients enjoy the excitement of a randomly generated number when the app is in production.

multiple Spring profiles in one application.properties file

It is possible to configure multiple Spring profiles in a single properties or YAML file.

Overriding the active Spring profile

During local development, the active Spring profile is selected based on the contents of the application.properties file. However, developers can override this property by passing a different value as an argument to the virtual machine, which enables them to set the profile differently in each environment.

Any class decorated with @Component, @Configuration, or @ConfigurationProperties can use Spring’s @Profile annotation to define its environment-specific behavior. This greatly simplifies the development of scalable applications that require customizable configuration across environments.