Using @Profile on @Beans annotated beans

In the previous post under Spring Core, I showed how to use “@Profile” annotation with “@Configuration” annotation.

In this post under Spring Core, I will show with example how to use “@Profile” annotation with “@Bean” annotation.

In previous post I also mentioned that “@Profile” annotation can be used with “@Configuration”, “@Bean”, and “@Component” annotation.

The difference between them being
1) if they are multiple objects that change based on the environment we are using, and they are declared using “@Bean” annotation we can group them in one separate configuration class and in that class, we apply the “@Profile” annotation at the class level. In this case, the entire configuration class is ignored if the profile name applied doesn’t match with the profile name given at the start of the application
2) if they are one or two objects that change based on the environment we are using, and they are declared using “@Bean” annotation in configuration classes along with other “@Bean” annotated methods, then we apply “@Profile” at the bean level. In this case, the entire bean declaration is ignored if the profile name applied doesn’t match with the profile name given at the start of the application
3) if they are objects that change based on the environment we are using, and they are declared using “@Component” annotation then we apply “@Profile” at each objects class level. In this case, the entire bean declaration is ignored if the profile name applied doesn’t match with the profile name given at the start of the application

In this post I will discuss the 2nd option. The 1st option was discussed in previous post.

To explain with example I will create marker interface as shown below

ICalculator

package package15;

public interface ICalculator {

}

Now I will create two different implementations of “ICalculator” interface one for production and another for testing as shown below

Production

package package15;

public class ProdCalculator implements ICalculator {
@Override
public String toString() {
return "Production Calculator";
}
}

Testing

package package15;

public class TestCalculator implements ICalculator {
@Override
public String toString() {
return "Test Calculator";
}
}

Next we will see the main class code which is also our “@Configuration” annotated class

Main class

1  package package15;
2
3 import org.springframework.context.ApplicationContext;
4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
5 import org.springframework.context.annotation.Bean;
6 import org.springframework.context.annotation.Configuration;
7 import org.springframework.context.annotation.Profile;
8
9 @Configuration
10 public class Example15 {
11 @Bean
12 @Profile({"prod", "default"})
13 public ICalculator prodCalculator() {
14 return new ProdCalculator();
15 }
16
17 @Bean
18 @Profile("test")
19 public ICalculator testCalculator() {
20 return new TestCalculator();
21 }
22
23 public static void main(String[] args) {
24 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Example15.class);
25 ICalculator calculator = applicationContext.getBean(ICalculator.class);
26 System.out.println(calculator);
27 }
28 }

In the above code, as you seen I have created two methods annotated with “@Bean” annotation.

“prodCalculator” method returns an instance of “ProdCalculator” class where as “testCalculator” returns an instance of “TestCalculator”.

Both the bean methods are annotated with “@Profile” annotation.

The “prodCalculator” bean method is annotated with ‘@Profile({“prod”,”default”})’. That means when the environment the application is running is “prod”, an instance of “ProdCalculator” is created
and the method “testCalculator” is ignored. Also if the environment information is not provided then also an instance of “ProdCalculator” is created.

Whereas when the environment the application is running on is “test”, an instance of “TestCalculator” is created and the method “prodCalculator” is ignored as it is for only “prod” and “default” profiles.

We can specify the profile or environment information at the start of the application by using the VM argument “-Dspring.profiles.active” as shown below.

    -Dspring.profiles.active=test

Note the profile name passed as VM argument must match with one of the profile names passed as argument to “@Profile” annotation.

In this way, we can use “@Profile” annotation with “@Bean” annotated methods.

Leave a comment