Spring and Spring Boot Journey

Week-02


Deep Dive into Spring and Spring Boot: Advanced Concepts

After learning the basics of Spring and Spring Boot last week, it's time to dive deeper into some advanced yet essential topics. This guide will help you understand concepts like Dependency Injection, Autowiring, XML Configurations, and more, with clear explanations and examples to help you grasp them easily.


Topics Covered

  1. Dependency Injection in Spring Boot

  2. Autowiring in Spring Boot

  3. Spring Without Boot

  4. Spring XML Configuration

  5. Constructor and Setter Injection in Spring Boot

  6. Advanced Autowiring in Spring Boot

  7. The Need for Spring Boot MVC


1. Dependency Injection in Spring Boot

What It Means:
Dependency Injection (DI) is a technique where the dependencies (other objects) of a class are provided from outside rather than being created inside the class. This makes the code cleaner, easier to test, and more reusable.

Code Example and Explanation:

@Service
public class UserService {
    private final UserRepository userRepository;

    // Dependency is injected via constructor
    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void performAction() {
        userRepository.saveData();
    }
}

Explanation:

  • UserService depends on UserRepository to perform some actions. Instead of creating a UserRepository instance inside UserService, we inject it using the constructor.

  • Spring automatically creates and injects the required UserRepository instance because of the @Autowired annotation.


2. Autowiring in Spring Boot

What It Means:
Autowiring is a feature of Spring that allows Spring to automatically inject the required beans into your class. This simplifies the process of wiring dependencies.

Code Example and Explanation:

@Component
public class OrderService {
    @Autowired
    private PaymentService paymentService;

    public void processOrder() {
        paymentService.makePayment();
    }
}

Explanation:

  • The @Autowired annotation tells Spring to inject an instance of PaymentService into OrderService.

  • No need to write new PaymentService()—Spring handles it for you.


3. Spring Without Boot

What It Means:
Spring Boot simplifies configuration, but sometimes you might need to set up a Spring application without it (e.g., for legacy projects). This involves creating beans and configuration manually.

Code Example and Explanation:

@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService(userRepository());
    }

    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
}

Explanation:

  • @Configuration marks this class as a configuration file.

  • @Bean creates and registers beans (like UserService and UserRepository) in the Spring application context.

This is less convenient but gives you full control over the configuration.


4. Spring XML Configuration

What It Means:
Before annotations became popular, Spring applications were configured using XML. Although less common now, it’s still used in some legacy systems.

Code Example and Explanation:

<beans>
    <bean id="userService" class="com.example.UserService">
        <property name="userRepository" ref="userRepository"/>
    </bean>
    <bean id="userRepository" class="com.example.UserRepository"/>
</beans>

Explanation:

  • The <bean> tag is used to define objects (UserService and UserRepository) in the XML file.

  • The ref attribute connects the userRepository to userService.


5. Constructor and Setter Injection in Spring Boot

What It Means:
These are two ways to inject dependencies into a class:

  1. Constructor Injection: Dependencies are passed through the class’s constructor.

  2. Setter Injection: Dependencies are set via setter methods.

Code Examples and Explanations:

Constructor Injection:

@Component
public class ProductService {
    private final ProductRepository productRepository;

    @Autowired
    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
}
  • The dependency (ProductRepository) is mandatory, so we inject it via the constructor.

Setter Injection:

@Component
public class CustomerService {
    private CustomerRepository customerRepository;

    @Autowired
    public void setCustomerRepository(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }
}
  • Setter injection is better for optional dependencies or cases where the dependency might change.

6. Advanced Autowiring in Spring Boot

What It Means:
When multiple beans of the same type exist, you can use @Qualifier to specify which one to inject.

Code Example and Explanation:

@Component
public class NotificationService {
    private final MessageSender messageSender;

    @Autowired
    public NotificationService(@Qualifier("emailSender") MessageSender messageSender) {
        this.messageSender = messageSender;
    }
}

Explanation:

  • The @Qualifier("emailSender") tells Spring to inject the emailSender bean into the NotificationService class, avoiding ambiguity.

7. The Need for Spring Boot MVC

What It Means:
Spring Boot MVC simplifies the creation of web applications by providing tools for building REST APIs, handling HTTP requests, and embedding servers.

Code Example and Explanation:

@RestController
@RequestMapping("/api")
public class UserController {
    @GetMapping("/users")
    public List<User> getAllUsers() {
        // Business logic to fetch users
        return new ArrayList<>();
    }
}

Explanation:

  • @RestController is used to create REST APIs.

  • @GetMapping maps HTTP GET requests to the getAllUsers method.


Real-World Example: E-commerce Application

Scenario:
Imagine an e-commerce app with the following components:

  1. ProductService to manage products.

  2. OrderService to handle customer orders.

  3. NotificationService to send emails or SMS for order updates.

Code Implementation:

@Service
public class ProductService {
    private final ProductRepository productRepository;

    @Autowired
    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
}

@Service
public class OrderService {
    private final OrderRepository orderRepository;
    private final NotificationService notificationService;

    @Autowired
    public OrderService(OrderRepository orderRepository, NotificationService notificationService) {
        this.orderRepository = orderRepository;
        this.notificationService = notificationService;
    }
}

@Service
public class NotificationService {
    @Autowired
    private EmailSender emailSender;

    public void sendNotification(String message) {
        emailSender.sendEmail(message);
    }
}

References

  1. Spring Framework Documentation

  2. Spring Boot Documentation

  3. Spring Boot Tutorial - YouTube Playlist by Navin Sir


Wrapping Up

Spring and Spring Boot are powerful frameworks that simplify Java application development, whether for small-scale projects or enterprise-grade systems.

Key Takeaways for Beginners:

  • Dependency Injection and Autowiring are central to how Spring manages objects and dependencies.

  • Understanding XML and manual configuration helps you work with legacy projects.

  • Spring Boot simplifies the process further, making it easier to create production-ready web applications with embedded servers and REST APIs.

By combining these concepts, you can build scalable, maintainable, and efficient Java applications. Don’t forget to apply what you’ve learned by creating small projects, like a task manager or e-commerce system, to reinforce these skills.

Happy coding! 🚀