Skip to content

Expert · Spring Boot basics · topic 51 of 60 · 25 min

Spring and dependency injection

Explanation

Spring is a framework whose core is an Inversion of Control (IoC) container: instead of your classes creating their own dependencies with new, Spring creates objects (beans) and passes ("injects") the dependencies they need. Classes marked @Component, @Service or @Repository become beans, and constructor injection is the recommended style. This makes code loosely coupled and easy to test.

The problem: new everywhere

java
public class OrderService {
    private final PaymentGateway gateway = new RazorpayGateway("live-key");   // hard-wired
    private final SmsSender sms = new TwilioSmsSender();                     // hard-wired
}

OrderService decides which payment gateway and SMS provider to use, creates them itself, and even holds a key. To test it without charging real cards, or to switch providers, you must edit OrderService. The classes are tightly coupled.

Dependency injection

Dependency injection (DI) means a class RECEIVES the objects it depends on, usually through its constructor, instead of creating them. Something outside (in Spring's case, the container) decides which implementation to pass. You already did this by hand with OtpService(SmsSender) in module 5.

java
@Service
public class OrderService {
    private final PaymentGateway gateway;
    private final SmsSender sms;

    public OrderService(PaymentGateway gateway, SmsSender sms) {   // constructor injection
        this.gateway = gateway;
        this.sms = sms;
    }
}

@Component
public class RazorpayGateway implements PaymentGateway { … }      // Spring creates this bean
@Component
public class SmsGatewaySender implements SmsSender { … }
With a single constructor, Spring injects it automatically; no @Autowired needed.

The container and beans

At start-up, Spring scans your packages for classes annotated as components, creates one object (a bean) of each by default (singleton scope), works out which beans need which others, and wires them together. This is Inversion of Control: the framework controls object creation, not your code.

AnnotationMeaning
@ComponentA general Spring-managed bean
@ServiceA bean holding business logic (same as @Component, clearer intent)
@RepositoryA bean that accesses data (also translates database exceptions)
@RestControllerA bean that handles HTTP requests (topic 3)
@Configuration + @BeanCreate beans in code, for example for third-party classes
java
@Configuration
public class ClockConfig {
    @Bean
    public java.time.Clock clock() {
        return java.time.Clock.system(java.time.ZoneId.of("Asia/Kolkata"));   // a bean you can inject anywhere
    }
}

Constructor versus field injection

You will see @Autowired on fields in older code (@Autowired private SmsSender sms;). Prefer constructor injection: the fields can be final, the dependencies are obvious, the object can never exist half-initialised, and tests can simply call new OrderService(fakeGateway, fakeSms) without Spring.

Careful: If two beans implement the same interface (two PaymentGateway beans), Spring cannot choose and start-up fails with "expected single matching bean but found 2". Mark one @Primary or select with @Qualifier("razorpay"). Also, a circular dependency (A needs B, B needs A) fails at start-up; it is usually a design problem to fix, not to work around.
Think of it like this: Without DI, every employee buys their own laptop, phone and SIM card. With DI, the company's IT department (the container) issues each new joiner exactly the equipment their role needs on day one. To test a new joiner's work, IT can hand them a test laptop instead.
Tip: If a class is hard to unit test, check whether it creates its dependencies with new. Moving them into the constructor usually fixes it.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Spring and dependency injection · 1/6

Spring and DI

In this lesson you will learn the core idea of Spring: dependency injection.

Prefer a video by a teacher? Find free videos on “spring dependency injection ioc container explained constructor injection” on YouTube ↗

In real life: Swapping SMS providers without touching business code

A clinic-booking startup moved from one SMS provider to another because of pricing. Because BookingService only depended on the SmsSender interface and received it through its constructor, the change was one new @Component class and marking it @Primary; BookingService and its tests did not change.

java
@Component
@Primary
public class NewProviderSmsSender implements SmsSender {
    public void send(String phone, String text) { /* call the new provider's API */ }
}

Practice (0/3 done)

Task 1 · Question

What is Inversion of Control in Spring?

Task 2 · Question

Two classes implement PaymentGateway and both are @Component. OrderService needs a PaymentGateway. What happens at start-up?

Task 3 · Practice

Without Spring, refactor a class ReportService that does "new EmailSender()" inside a method so that it receives a Sender interface through its constructor. Write a FakeSender for a test, and a main method that wires the real EmailSender by hand. Then explain in two sentences how Spring would do the wiring for you.

Quick quiz

Question 1

1.What is a Spring bean?

Question 2

2.Which injection style is recommended?

Question 3

3.What is the default scope of a Spring bean?

Question 4

4.Which annotation creates a bean from a method in a configuration class?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What is a Spring bean?

Answer: An object created and managed by the Spring container

Beans are container-managed objects.

Which injection style is recommended?

Answer: Constructor injection

Constructor injection gives final fields and easy tests.

What is the default scope of a Spring bean?

Answer: Singleton: one shared instance per container

Singleton by default.

Which annotation creates a bean from a method in a configuration class?

Answer: @Bean

@Bean methods inside @Configuration classes.

What is dependency injection?Related

Answer: Giving a class its dependencies from outside instead of it creating them

Dependencies are supplied, usually via the constructor.

From Dependency injection and service lifetimes

What does @Inject constructor do?Related

Answer: Tells Hilt how to create the class

Hilt calls it with the needed dependencies.

From Dependency injection with Hilt

Which server is embedded by default with spring-boot-starter-web?Related

Answer: Tomcat

Embedded Tomcat on port 8080.

From Creating a Spring Boot app

Spring implements @Transactional by wrapping beans in a…Related

Answer: Proxy

Proxies intercept calls to start and commit transactions.

From Common design patterns

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 4 more topics in “Spring Boot basics” before its exam: Creating a Spring Boot app, Building a REST API, Layers: controller, service and repository, JPA and Spring Data repositories.
  2. Module 11 exam: Spring Boot basics · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Design patterns, JVM internals and interviews. 60 topics left in the course before the final exam.

← Previous: Unit testing with JUnit