Inversion of Control (IoC) and Dependency Injection (DI) are two fundamental concepts in the Spring Framework. Traditionally, objects are responsible for creating and managing their own dependencies. However, IoC flips this responsibility by handing over the control of object creation and dependency management to a framework like Spring.
This shift offers several advantages:
IoC can be implemented through various mechanisms, including design patterns like the Factory Pattern, Strategy Pattern, or Service Locator Pattern. However, the most common and powerful way to achieve IoC is through Dependency Injection.
Dependency Injection (DI) is a technique where the framework injects dependencies into an object rather than the object creating the dependencies itself. There are different types of DI in Spring:
For example, in a simple service class, you might see something like this:
@Service public class OrderService { private final PaymentService paymentService; @Autowired public OrderService(PaymentService paymentService) { this.paymentService = paymentService; } public void processOrder(Order order) { paymentService.processPayment(order.getPaymentDetails()); } }
Here, PaymentService is injected into OrderService via constructor injection, which is generally preferred for its clear dependencies and ease of testing.
Spring provides an IoC container that is responsible for managing the lifecycle of beans (objects managed by Spring). The basic interface for this container is BeanFactory. However, most applications use ApplicationContext, which extends BeanFactory and offers additional features.
// Getting a bean from the ApplicationContext ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyBean myBean = context.getBean(MyBean.class);
In this example, ApplicationContext is used to retrieve a bean. If you were using a basic BeanFactory, it would offer similar functionality but without the additional benefits of ApplicationContext.
There are two common ways to access the current ApplicationContext:
Autowired: Inject the ApplicationContext directly into your component.
@Autowired private ApplicationContext applicationContext;
ApplicationContextAware: Implement the ApplicationContextAware interface, which allows you to retrieve the ApplicationContext as needed.
public class MyBean implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext context) throws BeansException { this.applicationContext = context; } }
When a Spring application starts, a series of steps take place:
Processing Environment Variables and Properties: The Environment object is created, incorporating settings from application.properties or application.yml.
Creating the ApplicationContext: The appropriate ApplicationContext type is determined and instantiated. For instance, a Spring Boot application may use AnnotationConfigServletWebServerApplicationContext for Java-based configurations.
Loading Bean Definitions: Spring loads bean definitions from multiple sources, such as annotated classes, @Configuration classes, or XML files. Each bean definition includes information about the bean's type, scope, dependencies, and lifecycle callbacks.
Processing BeanFactoryPostProcessors: These processors modify the bean definitions before the actual beans are created.
Dependency Resolution and Bean Creation: The ApplicationContext resolves dependencies and creates the beans. If a bean has dependencies on other beans, those dependencies are created first.
Spring supports various bean scopes, which define the lifecycle and visibility of a bean within the container:
@Bean @Scope("prototype") public MyPrototypeBean myPrototypeBean() { return new MyPrototypeBean(); }
In this example, a new MyPrototypeBean instance is created each time it is requested from the container.
Consider a scenario where a Singleton-scoped bean depends on a Prototype-scoped bean. Normally, the prototype bean would only be created once during the singleton's initialization. To ensure that a new instance of the prototype bean is provided each time, Spring uses proxy objects.
@Component @Scope(value = "singleton") public class SingletonBean { @Autowired @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) private PrototypeBean prototypeBean; public void showMessage() { System.out.println(prototypeBean.getMessage()); } }
Here, ScopedProxyMode.TARGET_CLASS ensures that a new PrototypeBean instance is returned each time getMessage() is called.
Spring Boot is an extension of the Spring Framework that simplifies the setup and development of new Spring applications. It provides:
Auto-Configuration is a powerful feature in Spring Boot that configures many things for you based on the dependencies in your classpath. This is controlled by conditional annotations such as:
For instance, if you have Jackson on your classpath, Spring Boot will automatically configure an ObjectMapper for JSON serialization:
@Configuration @ConditionalOnClass(ObjectMapper.class) public class JacksonAutoConfiguration { // Configuration details... }
If ObjectMapper is present, this configuration is automatically applied. Otherwise, it is skipped.
You can log the active auto-configurations during startup by adding the following to your application.properties:
logging.level.org.springframework.boot.autoconfigure=DEBUG
This will generate a detailed report showing which configurations were applied and which were not, helping you troubleshoot or understand the application's configuration.
Inversion of Control and Dependency Injection are core concepts that enable the flexibility, modularity, and testability that make Spring so powerful. By understanding how Spring's IoC container works, how beans are managed, and how Spring Boot extends these capabilities, you can develop robust, maintainable applications more efficiently.
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3