Demystifying Spring: A Beginner’s Journey into Spring Framework and Spring Boot (2 Part Series)
1 Demystifying Spring: A Beginner’s Journey into Spring Framework and Spring Boot
2 Week 1: Spring Core
Week 1: Demystifying the Spring Framework – Understanding the Core Concepts
Welcome to the first week of my journey into the Spring ecosystem! This article marks the beginning of my attempt to truly understand how Spring Framework works under the hood, particularly focusing on some of its most foundational concepts: IoC, Dependency Injection, Beans, and the ApplicationContext.
Before diving in, let’s first clarify a common confusion: Spring Framework vs.
Spring Boot.
Spring Framework vs. Spring Boot
Many newcomers (like myself) initially get confused between Spring Framework and Spring Boot, since they’re often used together. Here’s a simple breakdown:
Aspect | Spring Framework | Spring Boot |
---|---|---|
Purpose | A comprehensive, modular Java framework for building enterprise apps | A layer on top of Spring that simplifies setup and configuration |
Configuraiton | Requires manual setup of beans, XML or Java-based config | Convention over configuration (sensible defaults, auto-config) |
Starter Packs | None | Comes withe “starters” for web, JPA, security, etc. |
Use Case | When you need full control over the setup and structure | When you want to get started quickly with minimal config |
Built On | Core Spring modules | Core Spring modules (it’s not a replacement!) |
So in essence, Spring Boot helps you build apps faster, but it’s still powered by Spring Framework underneath.
Here’s an illustration of how the dependency works:
What is Inversion of Control (IoC)?
IoC is the design principle at the heart of Spring. Normally in programming, you control how and when objects are created. But with IoC, you delegate that control to the framework.
Instead of writing code like this:
<span>Service</span> <span>myService</span> <span>=</span> <span>new</span> <span>Service</span><span>();</span><span>Service</span> <span>myService</span> <span>=</span> <span>new</span> <span>Service</span><span>();</span>Service myService = new Service();
Enter fullscreen mode Exit fullscreen mode
Spring handles the object creation and injects it wherever it’s needed. This
inversion of control reduces tight coupling and increases flexibility. Thus, you
simply specify the dependency on your constructor and Spring will supply if for
you.
<span>public</span> <span>Controller</span><span>(</span><span>Service</span> <span>service</span><span>)</span> <span>{</span><span>this</span><span>.</span><span>service</span> <span>=</span> <span>service</span><span>;</span><span>}</span><span>public</span> <span>Controller</span><span>(</span><span>Service</span> <span>service</span><span>)</span> <span>{</span> <span>this</span><span>.</span><span>service</span> <span>=</span> <span>service</span><span>;</span> <span>}</span>public Controller(Service service) { this.service = service; }
Enter fullscreen mode Exit fullscreen mode
Dependency Injection (DI)
DI is a specific implementation of IoC where the framework injects the dependencies (i.e., other objects a class needs) automatically.
There are different types of DI:
- Constructor Injection (recommended)
- Setter Injection
- Field Injection (less preferred)
Example Constructor Injection:
<span>@Component</span><span>public</span> <span>class</span> <span>UserService</span> <span>{</span><span>private</span> <span>final</span> <span>UserRepository</span> <span>userRepository</span><span>;</span><span>@Autowired</span><span>public</span> <span>UserService</span><span>(</span><span>UserRepository</span> <span>userRepository</span><span>)</span> <span>{</span><span>this</span><span>.</span><span>userRepository</span> <span>=</span> <span>userRepository</span><span>;</span><span>}</span><span>}</span><span>@Component</span> <span>public</span> <span>class</span> <span>UserService</span> <span>{</span> <span>private</span> <span>final</span> <span>UserRepository</span> <span>userRepository</span><span>;</span> <span>@Autowired</span> <span>public</span> <span>UserService</span><span>(</span><span>UserRepository</span> <span>userRepository</span><span>)</span> <span>{</span> <span>this</span><span>.</span><span>userRepository</span> <span>=</span> <span>userRepository</span><span>;</span> <span>}</span> <span>}</span>@Component public class UserService { private final UserRepository userRepository; @Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; } }
Enter fullscreen mode Exit fullscreen mode
Here, Spring automatically injects a UserRepository instance when creating UserService. However, this is no longer necessary if the target bean has only one constructor, full link here.
Example Setter Injection:
<span>public</span> <span>class</span> <span>SimpleMovieLister</span> <span>{</span><span>private</span> <span>MovieFinder</span> <span>movieFinder</span><span>;</span><span>@Autowired</span><span>public</span> <span>void</span> <span>setMovieFinder</span><span>(</span><span>MovieFinder</span> <span>movieFinder</span><span>)</span> <span>{</span><span>this</span><span>.</span><span>movieFinder</span> <span>=</span> <span>movieFinder</span><span>;</span><span>}</span><span>// ...</span><span>}</span><span>public</span> <span>class</span> <span>SimpleMovieLister</span> <span>{</span> <span>private</span> <span>MovieFinder</span> <span>movieFinder</span><span>;</span> <span>@Autowired</span> <span>public</span> <span>void</span> <span>setMovieFinder</span><span>(</span><span>MovieFinder</span> <span>movieFinder</span><span>)</span> <span>{</span> <span>this</span><span>.</span><span>movieFinder</span> <span>=</span> <span>movieFinder</span><span>;</span> <span>}</span> <span>// ...</span> <span>}</span>public class SimpleMovieLister { private MovieFinder movieFinder; @Autowired public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // ... }
Enter fullscreen mode Exit fullscreen mode
Example Field Injection:
<span>public</span> <span>class</span> <span>MovieRecommender</span> <span>{</span><span>private</span> <span>final</span> <span>CustomerPreferenceDao</span> <span>customerPreferenceDao</span><span>;</span><span>@Autowired</span><span>private</span> <span>MovieCatalog</span> <span>movieCatalog</span><span>;</span><span>@Autowired</span><span>public</span> <span>MovieRecommender</span><span>(</span><span>CustomerPreferenceDao</span> <span>customerPreferenceDao</span><span>)</span> <span>{</span><span>this</span><span>.</span><span>customerPreferenceDao</span> <span>=</span> <span>customerPreferenceDao</span><span>;</span><span>}</span><span>// ...</span><span>}</span><span>public</span> <span>class</span> <span>MovieRecommender</span> <span>{</span> <span>private</span> <span>final</span> <span>CustomerPreferenceDao</span> <span>customerPreferenceDao</span><span>;</span> <span>@Autowired</span> <span>private</span> <span>MovieCatalog</span> <span>movieCatalog</span><span>;</span> <span>@Autowired</span> <span>public</span> <span>MovieRecommender</span><span>(</span><span>CustomerPreferenceDao</span> <span>customerPreferenceDao</span><span>)</span> <span>{</span> <span>this</span><span>.</span><span>customerPreferenceDao</span> <span>=</span> <span>customerPreferenceDao</span><span>;</span> <span>}</span> <span>// ...</span> <span>}</span>public class MovieRecommender { private final CustomerPreferenceDao customerPreferenceDao; @Autowired private MovieCatalog movieCatalog; @Autowired public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) { this.customerPreferenceDao = customerPreferenceDao; } // ... }
Enter fullscreen mode Exit fullscreen mode
🫘 What are Beans?
A Bean is simply an object that is managed by the Spring container. You define a bean by annotating a class with @Component
, @Service
,
@Repository
, or by using @Bean
in a configuration class.
<span>@Component</span><span>public</span> <span>class</span> <span>EmailService</span> <span>{</span><span>public</span> <span>void</span> <span>sendEmail</span><span>(</span><span>String</span> <span>to</span><span>,</span> <span>String</span> <span>message</span><span>)</span> <span>{</span><span>// send email</span><span>}</span><span>}</span><span>@Component</span> <span>public</span> <span>class</span> <span>EmailService</span> <span>{</span> <span>public</span> <span>void</span> <span>sendEmail</span><span>(</span><span>String</span> <span>to</span><span>,</span> <span>String</span> <span>message</span><span>)</span> <span>{</span> <span>// send email</span> <span>}</span> <span>}</span>@Component public class EmailService { public void sendEmail(String to, String message) { // send email } }
Enter fullscreen mode Exit fullscreen mode
This class becomes a Spring-managed bean, meaning Spring takes care of its lifecycle and dependencies.
️ ApplicationContext: The Spring Container
The ApplicationContext is the core interface of the Spring container. It holds all the beans and manages their life cycles.
Think of it as a registry that:
- Creates and wires beans
- Manages their scopes
- Provides internationalization
- Handles event propagation
When you create a Spring Boot app, ApplicationContext is automatically initialized for you. In traditional Spring, you might initialize it manually like this:
<span>ApplicationContext</span> <span>context</span> <span>=</span> <span>new</span> <span>AnnotationConfigApplicationContext</span><span>(</span><span>AppConfig</span><span>.</span><span>class</span><span>);</span><span>MyService</span> <span>service</span> <span>=</span> <span>context</span><span>.</span><span>getBean</span><span>(</span><span>MyService</span><span>.</span><span>class</span><span>);</span><span>ApplicationContext</span> <span>context</span> <span>=</span> <span>new</span> <span>AnnotationConfigApplicationContext</span><span>(</span><span>AppConfig</span><span>.</span><span>class</span><span>);</span> <span>MyService</span> <span>service</span> <span>=</span> <span>context</span><span>.</span><span>getBean</span><span>(</span><span>MyService</span><span>.</span><span>class</span><span>);</span>ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); MyService service = context.getBean(MyService.class);
Enter fullscreen mode Exit fullscreen mode
Final Thoughts
Understanding IoC, DI, Beans, and the ApplicationContext helps demystify a large part of Spring. These concepts might seem abstract at first, but they are the foundation that powers the rest of the framework—and every feature you’ll use in Spring Boot.
⏭️ Up Next: Week 2 – Spring Boot Basics
Next week, we’ll explore how Spring Boot simplifies setup using auto-configuration, starter dependencies, and devtools. I’ll walk through building your first Spring Boot app from scratch.
If you have any feedback, corrections, or ideas, feel free to share them. See you in the next one!
Demystifying Spring: A Beginner’s Journey into Spring Framework and Spring Boot (2 Part Series)
1 Demystifying Spring: A Beginner’s Journey into Spring Framework and Spring Boot
2 Week 1: Spring Core
原文链接:Week 1: Spring Core
暂无评论内容