background

Spring uses the IOC (Inversion of Control) model to store objects in the Spring container. Whenever we want to use objects, we can get bean objects from the container through dependency injection.

Since bean objects are handed over to the container for management, the concept of a life cycle comes into being. This life cycle includes not only the container life cycle, but also the bean object life cycle.

Spring’s container

Spring has two containers: BeanFactory and ApplicationContext.

The difference between:

  • The BeanFactory provides only basic bean storage and dependency injection capabilities, and version control capabilities.
  • ApplicationContext inherits all of the features of BeanFactory and provides a number of extensions for configuration-specific internationalization, event propagation, resource loading, and support for SOME J2EE features.
  • BeanFactory beans are lazy-loaded, meaning that scanned objects are not instantiated when the container is created, but are instantiated when injected for use.
  • The ApplicationContext is non-delayed-loading, that is, the bean object is initialized as soon as the container is initialized.

The life cycle of the bean

  1. Instantiating the Spring container (applicationContext)
  2. Scan classes that conform to springBean rules (rules: @ComponentScan, @Bean, etc.)
  3. Iterate over the scanned class, encapsulating it in a beanDefinitionMap object. (Can be interpreted as a drawing, which contains information about bean classes, such as abstract classes, lazy loading, etc.)
  4. If the BeanFactoryProcessor class is used, it interferes with the original class definition, the intervention drawing.
  5. Traversing beanDefinitionMjap (drawing), obtaining the class information, then deduce the reasonable construction method of this class through the algorithm.
  6. An object is reflected from this constructor.
  7. Level 3 cache, performing cyclic dependency injection. (Explained below)
  8. Implement the Aware interface (BeanNameAware, BeanClassLoaderAware, BeanFactoryAware)
  9. The BeanPostProcessor interface connection if beans, it will call postProcessBeforeInitialization method, mainly is to change the content of the bean.
  10. Execute the bean’s initialization method init-method.
  11. The BeanPostProcessor interface connection if beans, it will also call postProcessAfterInitialization method.
  12. Perform AOP dynamic proxies (such as event distribution, release listening, etc.)
  13. Put the bean into the singleton pool singletonObjects.
  14. Destroy, destroy().

Dependency injection

Dependency injection is also a circular dependency, in which two or more beans hold each other in a closed loop. For example, A depends on B, and B depends on A.

Insert a picture description here

Problem: When A is initialized, it cannot be initialized because B is not present. When B initializes, it cannot initialize because there is no A, causing A deadlock.

So how do you create these two bean objects in the Spring container? Spring adopts the concept of three-level caching.

Level 3 cache:

  1. SingletonFactories: Singleton object factories, where bean objects are produced.
  2. EarlySingletonObjects: singleton objects that are pre-exposed (not initialized, but already in shape)
  3. SingletonObjects: Caches that can be used directly.

Steps:

  1. When A is initialized, it is instantiated in the factory and put into the pre-exposed singleton cache.
  2. When A wants to inject property B, the object B is not found, so B is created first.
  3. When B is initialized, it is also instantiated in the factory and put into the pre-exposed singleton cache.
  4. To inject property A, B first looks for it in the singleton cache, fails to find it, and then looks for it in the pre-exposed cache. If A is found, A is injected.
  5. Create A after B is created.
  6. Since B injects A reference to A, A’s operations after initialization are also visible to B.