We were talking about Inversion of Control and how Dependency Injection helps to handle its complexity.
However, there are some trade off we must make base on our project to not add unneeded complexity.
I will use Spring Boot as an example.
TRY IT YOURSELF: You can find this post source code here.
Dependency Inversion Series
- Part 1: Dependency Inversion: why you should NOT avoid it
- Part 2: Main and Abstraction: The decoupled peers
- Part 3: Inversion of Control: Putting All Together
- Part 4: Dependency Injection: Solving the Inversion of Control complexity
- Part 5: Factory Methods: Decoupling the IoC Container from the Abstraction (You are here)
Let’s do our best: Using @Configuration
Let’s use our previous example:

We see how @Service annotation is creating a compile time dependency, so, you really are not totally decoupled from Spring IoC.
Spring Component Annotations: Advantages and Disadvantages
Well, we can use @Component and @Service (together with other like @Repository or @RestController) to define a Spring bean.
This strategy has the following advantages:
- Easy to understand, when you see a class with those annotations you know they are Spring beans.
- Fast to code, you only need to add the annotation and that’s all (NOTE: Spring needs to find them, be sure to have a good component scan setup.
And disadvantages:
- Compile time dependency, as you are adding annotations to your business logic, so, you are coupling your Abstraction, with your IoC container.
- Dirty code, you shouldn’t care about IoC containers in your business logic.
Spring Factory Pattern: @Bean
Spring gives us a way to avoid adding annotations to our Abstraction.
So, let’s move our current implementation to a better state:
public class MySQLRepository implements Repository{ //TODO constructor and behavior }
MySQLRepository doesn’t change too much.
public class Service{ private final Repository repository; public Service(Repository repository){ this.repository = repository; } //TODO behavior }
Notice that those classes are pure Abstraction, they don’t know about the IoC container.
@SpringBootApplication public class Starter{ public static void main(String[] args){ //Starting IoC container ApplicationContext iocContainer = SpringApplication.run(Starter.class, args); //Getting Service object from the IoC container Service service = iocContainer.getBean("service", Service.class); //TODO use service behavior } }
Our Main doesn’t change at all. However, we add another part to our Main that is responsible to tell Spring how to create and handle our beans, the @Configuration.
@Configuration public class ApplicationFactory{ @Bean public Repository repository(){ return new MySQLRepository(); } @Bean public Service service(Repository repository){ return new Service(repository); } }
Before, we use @Service and @Component to tell Spring which classes it must handle. Spring was in charge of instantiation and injection.
Now, @Configuration tells Spring that that class is a factory of beans. It means the developer is in charge of defining how to create beans.
Each factory method is defined by @Bean annotation. Moreover, you can use Dependency Injection to use beans created by other factory methods, like you see in line 10.
Now, let’s see how our application looks like:

Well, this approach has the following advantages:
- There is not more annotation dependency, our Abstraction is totally free.
- We control how the beans are created, so, you can add logic and complex builders to the beans.
- We can test easily the factory methods, if we think it is worth.
And disadvantages:
- More code to maintain, we should write factory methods by bean.
- Difficult to follow and understand, in a real project, we could have a lot of beans, therefore, a lot of factory classes.
TRY IT YOURSELF: You can find this source code here.
Final Thought
Factory methods are a pretty good way to avoid coupling against IoC containers, however, we should trade off those decisions base on the project needs.
If you liked this post and are interested in hearing more about my journey as a Software Engineer, you can follow me on Twitter and travel together.
[…] a next post, I am going to be cleaner, and avoid this dependency using Spring Boot and @Configuration annotation as an […]
LikeLike
Thanks for the posts, I understood how Spring and SpringBoot work =)
LikeLike
[…] use the following example we saw on a previous […]
LikeLike
[…] Part 5: Factory Methods: Decoupling the IoC Container from the Abstraction […]
LikeLike
[…] Part 5: Factory Methods: Decoupling the IoC Container from the Abstraction […]
LikeLike
[…] Part 5: Factory Methods: Decoupling the IoC Container from the Abstraction […]
LikeLike
[…] REMEMBER: You should decouple your business logic from the IoC container, for instance, using @Bean in Spring or @Produce in JakartaEE. You can read more here Factory Methods: Decoupling the IoC Container from the Abstraction […]
LikeLike
[…] define a TemplatesFactory class. This class has multiple factory methods, one by each object we handle in our […]
LikeLike
[…] https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/ […]
LikeLike