This is something that can be very useful when running your application in different environments. One case is that you want to place messages on a queue but you do not have access to the queue manager in the development environment. Here is an example of what a solution might be to that problem:
First, we create an interface that can act as a facade for our “send” method
public interface Gateway { void send(Message message); }
Now we need to add this interface to our class
public class MQGateway implements Gateway { @Override void send(Message message){ /* All the logic needed to send a message */ } }
And now we create two Beans. One for each profile
@Bean @Profile("dev") public MQGateway mqgatewayDevelop() { return new MQGateway() { @Override void send(Message message) { log.info("Mocked gateway. Sending message to log: " + message); } } } @Bean @Profile("prod") public MQGateway mqgatewayProduction() { return new MQGateway(); }
I usually put Bean creation in a configuration class so that any setting from application.yml is close at hand
And now we are going to use some “magic” to make Spring choose the right one
public class MyClass { @Autowire private Gateway mqGateway; public void myFunction(Message message) { mqGateway.send(message); } }
So, how does this work. Well, by using the interface when calling the ‘send’ method we are forcing Sprint to find a suitable Bean of that type and since there only will be one active per profile Spring will find the right one.
If Spring can’t find a suitable Bean it will throw a exception
Tested on Spring Boot v2.2.4