1. Introduction

In this tutorial, we're going to investigate Spring profiles. By using Spring profiles we can restrict the creation of beans to specific environments. For example, we can use an in-memory database for the development environment, whereas we use a full-fledged database on the production environment.

2. What is A Spring Profile?

Now let's look at what a profile is, using some examples.

Firstly, a profile can represent an environment. For example, we can have profiles like development, test or prod.

Secondly, we can capture some aspect of the environment by profiles. For example, we can create profiles like fast, slow, lowMemory or highMemory.

Additionally, we can also use profiles to divide our application into several sub-applications. Some examples are messaging, rest-api or monitoring.

3. Assigning a Spring Profile To a Bean

Now, let's see how we can assign a profile to a bean.

Spring provides the @Profile annotation for assigning profiles:

@Component
@Profile("prod")
public class RealEmployeeService implements EmployeeService{
}

Here, we have the RealEmployeeService bean. We're also supplying the @Profile annotation with the value of prod. As a result, Spring will register RealEmployeeService only when the active profiles include prod.

4. Spring Profile Expressions

Previously, we've only defined one profile in the @Profile annotation. But, we can also create profile expressions to capture more complex requirements.

Firstly, we'll express logical and of profiles:

@Component
@Profile("prod & fast")
public class FastProdEmployeeService implements EmployeeService{
}

Here, Spring will register the FastProdEmployeeService bean when both prod and fast are active.

We can also create logical or of profiles:

@Component
@Profile("prod | slow")
public class SlowProdEmployeeService implements EmployeeService{
}

In this case, Spring will register the SlowProdEmployeeService bean when either prod or slow is active.

Lastly, we can express the negation of a profile:

@Component
@Profile("!prod")
public class MockEmployeeService implements EmployeeService{
}

Here, Spring will register MockEmployeeService whenever the prod profile is not active.

Lastly, if want to use & and | operators in the same expression, we should use parentheses.

5. Activating Spring Profiles

Now that we've seen assigning profiles to our beans, we'll look at next how we can activate a profile.

To achieve this, we should set the desired profiles when starting the application context.

5.1. Setting Active Profiles using the Environment API

Firstly, we'll use the Environment API to set the active profiles:

@Configuration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(Application.class);
        applicationContext.getEnvironment().setActiveProfiles("prod, fast");
        applicationContext.refresh();

        applicationContext.close();
    }
}

Here, we're calling applicationContext.getEnvironment().setActiveProfiles("prod, fast") to set the active profiles as prod and fast. As a result, Spring registers the beans of prod and fast, and also the beans without any profile.

5.2. Setting Active Profiles using spring.profiles.active

Alternatively, we can also activate profiles using the spring.profiles.active property.

We'll first pass this value as a JVM system property when starting our application:

-Dspring.profiles.active="prod,fast"

We can also define this property as an environment property using the property files - application.properties:

spring.profiles.active=prod,fast

5.3. Setting Active Profiles for Tests using @ActiveProfiles

Spring also provides the @ActiveProfies annotation for setting active profiles for test classes:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Application.class)
@ActiveProfiles({"fast", "prod"})
public class ApplicationTest {

    @Autowired
    private Environment environment;

    @Test
    public void shouldActivateProfiles() {
        String[] activeProfiles = environment.getActiveProfiles();

        assertThat(activeProfiles).containsOnly("fast", "prod");
    }
}

Here, we're specifying the active profiles as fast and prod.

6. Default Profile

So far, we've activated the profiles explicitly. However, when we don't activate a profile, Spring uses the default profile as the active one.

We can assign the default profile to our beans:

@Component
@Profile("default")
public class DefaultEmployeeService {
}

Here, Spring will register DefaultEmployeeService when no profile is activated.

There are some important points to note about the default profile. Firstly, the beans without a profile assignment don't belong to the default profile. Spring always registers these beans during the application startup. Secondly, when a profile is activated, the default profile is ignored. Hence Spring won't register the beans assigned with default.

6.1. Setting the Default Profile

Now, we'll see how to define a different default profile.

For this purpose, we'll first use the Environment API:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(Application.class);
applicationContext.getEnvironment().setDefaultProfiles("fast");
applicationContext.refresh();

Or similar to spring.profiles.active, we can use the spring.profiles.default property:

-Dspring.profiles.default="fast"

7. Summary

In this tutorial, we've looked at how we can assign and activate Spring profiles.

As always, the source code for all examples in this article is available on Github.