Spring Framework Tutorial

Software Setup and Configuration (STS/Eclipse/IntelliJ)

Core Spring

Spring Annotations

Spring Data

Spring JDBC

Spring Security

Spring Inversion of Control with Example

Inversion of Control (IoC) is a design principle where the control of the flow of a program is inverted: instead of the program code dictating how and when specific tasks are done, a framework or container makes these decisions. In the context of the Spring framework, IoC refers to the Spring container taking care of creating and managing beans.

The primary advantage of IoC is that it promotes decoupling, making code easier to test and maintain.

Let's walk through a basic example of IoC using Spring.

1. Java Classes:

Interface - A simple service interface:

public interface MessageService {
    void sendMessage(String msg, String recipient);
}

Implementation - Implementation of the service interface:

public class EmailService implements MessageService {

    @Override
    public void sendMessage(String msg, String recipient) {
        // Logic to send an email
        System.out.println("Email sent to " + recipient + " with message=" + msg);
    }
}

Consumer - A consumer class which depends on the MessageService:

public class MessageServiceConsumer {
    private MessageService service;

    // Constructor-based dependency injection
    public MessageServiceConsumer(MessageService svc) {
        this.service = svc;
    }

    public void processMessage(String msg, String recipient) {
        this.service.sendMessage(msg, recipient);
    }
}

2. Spring Configuration:

Now, you would configure the Spring container to manage these beans using XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- Message Service bean -->
    <bean id="messageService" class="EmailService" />

    <!-- Message Consumer bean -->
    <bean id="consumer" class="MessageServiceConsumer">
        <constructor-arg ref="messageService"/>
    </bean>

</beans>

3. Testing the Configuration:

Now, let's test our configuration to see IoC in action:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IoCExample {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        MessageServiceConsumer consumer = (MessageServiceConsumer) context.getBean("consumer");
        consumer.processMessage("Hello, IoC!", "test@domain.com");
    }
}

When you run the IoCExample, you should see the message indicating that an email was sent.

In this example, the MessageServiceConsumer doesn't create an instance of EmailService directly. Instead, it's handed to it (injected) by the Spring container - this is the Inversion of Control. The benefit is that you can change the MessageService implementation (e.g., switch to an SMSService) without modifying the MessageServiceConsumer class, only the Spring configuration.

  1. Using constructor injection in Spring IoC:

    • Description: Demonstrates how to use constructor injection for dependencies in Spring IoC.
    • Code:
      public class MyService {
          private final MyRepository myRepository;
      
          public MyService(MyRepository myRepository) {
              this.myRepository = myRepository;
          }
      }
      
  2. Setter injection in Spring IoC container:

    • Description: Shows how to use setter injection for dependencies in Spring IoC.
    • Code:
      public class MyService {
          private MyRepository myRepository;
      
          public void setMyRepository(MyRepository myRepository) {
              this.myRepository = myRepository;
          }
      }
      
  3. IoC container configuration in Spring XML:

    • Description: Demonstrates how to configure the Spring IoC container using XML.
    • Code:
      <beans>
          <bean id="myService" class="com.example.MyService">
              <property name="myRepository" ref="myRepository"/>
          </bean>
      
          <bean id="myRepository" class="com.example.MyRepository"/>
      </beans>
      
  4. Annotation-based configuration for IoC in Spring:

    • Description: Shows how to configure the Spring IoC container using annotations.
    • Code:
      @Service
      public class MyService {
          @Autowired
          private MyRepository myRepository;
      }
      
  5. IoC container initialization and destruction methods:

    • Description: Explains how to define initialization and destruction methods for beans in the Spring IoC container.
    • Code:
      public class MyService {
          @PostConstruct
          public void init() {
              // Initialization logic
          }
      
          @PreDestroy
          public void cleanup() {
              // Destruction logic
          }
      }
      
  6. Configuring beans with JavaConfig in Spring IoC:

    • Description: Guides on configuring Spring beans using JavaConfig (Java-based configuration).
    • Code:
      @Configuration
      public class AppConfig {
          @Bean
          public MyService myService() {
              return new MyService(myRepository());
          }
      
          @Bean
          public MyRepository myRepository() {
              return new MyRepository();
          }
      }