Hello, today I would like to share Spring IOC with you. Please take out your notebook and write it down.

The SpringIOC container initializes the body process

Spring IoC’s container architecture

IoC container is the core module of Spring, which abstracts object management and dependency management framework solution. Spring provides a number of containers, of which the BeanFactory is the top-level (root) container and cannot be instantiated. It defines a set of principles that all IoC containers must follow. Specific container implementations can add additional functionality, such as the common ApplicationContext. Its more specific implementation such as ClassPathXmlApplicationContext contains content, parse the XML and a series of AnnotationConfigApplicationContext is includes annotations and so on a series of content. The Spring IoC container inheritance system is smart enough to use whichever layer you need, rather than the full-featured one. The BeanFactory top-level interface method stack is as follows

BeanFactory container inheritance system

From its interface design, we can see that the ApplicationContext we always use inherits the BeanFactory sub-interface, ResourceLoader, MessageSource, etc., so it provides richer functionality.

Below we ClasspathXmlApplicationContext, for example, deep source of IoC container initialization process.

Bean lifecycle critical timing points

Create a class Bean, let it implement several special interfaces, and respectively in the constructor of interface implementation, interface method breakpoint, observe the thread call stack, analyze the Bean object creation and management key trigger time.

LagouBean class

package com.lagou;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.DisposableBean;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;

import org.springframework.beans.factory.config.BeanPostProcessor;

import

org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.stereotype.Component;

public class LagouBean implements InitializingBean{

/ * *

  • The constructor

* /

public LagouBean(){

System.out.println(“LagouBean constructor… );

}

/ * *

  • InitializingBean interface implementation

* /

public void afterPropertiesSet() throws Exception {

System.out.println(“LagouBean afterPropertiesSet…” );

}

}

BeanPostProcessor interface implementation class

package com.lagou;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.BeanPostProcessor;

import org.springframework.stereotype.Component;

public class MyBeanPostProcessor implements BeanPostProcessor {

public MyBeanPostProcessor() {

System.out.println(“BeanPostProcessor implements class constructor… );

}

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {

if(“lagouBean”.equals(beanName)) {

System. Out.println (” BeanPostProcessor implementation class

PostProcessBeforeInitialization method is invoked in…” );

}

return bean;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {

if(“lagouBean”.equals(beanName)) {

System. Out.println (” BeanPostProcessor implementation class

PostProcessAfterInitialization method is invoked in…” );

}

return bean;

}

}

BeanFactoryPostProcessor interface implementation

package com.lagou;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;

import

org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.stereotype.Component;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

public MyBeanFactoryPostProcessor() {

System.out.println(“BeanFactoryPostProcessor implementation class constructor…” );

}

@Override

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

System.out.println(“BeanFactoryPostProcessor implementation method call……” );

}

}

applicationContext.xm

The < beans XMLNS = “www.springframework.org/schema/bean…”

XMLNS: xsi = “www.w3.org/2001/XMLSch…”

xsi:schemaLocation=”

www.springframework.org/schema/bean…

www.springframework.org/schema/bean…

“>

<bean id=”myBeanFactoryPostProcessor”

class=”com.lagou.MyBeanFactoryPostProcessor”/>

IoC container source code analysis use cases

/ * *

  • Ioc container source code analysis base case

* /

@Test

public void testIoC() {

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“classpath:applicationContext.xml”);

LagouBean lagouBean = applicationContext.getBean(LagouBean.class);

System.out.println(lagouBean);

}

Analyze whether the Bean is created when the container is initialized or when the getBean is created

Based on breakpoint debugging, we found that without lazy loading, the Bean was created during container initialization.

Analyze constructor calls

Observe the call stack:

By the above observation, we found that the constructor calls time on AbstractApplicationContext class finishBeanFactoryInitialization refresh methods (the beanFactory);

Analyze the afterPropertiesSet initialization method call for InitializingBean

From the above observation, We found the afterPropertiesSet in the InitializingBean Method calls in AbstractApplicationContext timing and refresh methods finishBeanFactoryInitialization (the beanFactory);

Analyze BeanFactoryPostProcessor initialization and invocation

Observe the call stack at the break point at the constructor, postProcessBeanFactory method, Find spring BeanFactoryPostProcessor initialization AbstractApplicationContext class invokeBeanFactoryPostProcessors refresh methods (the beanFactory); PostProcessBeanFactory calls in invokeBeanFactoryPostProcessors AbstractApplicationContext classes refresh methods (the beanFactory);

Analyze BeanPostProcessor initialization and invocation

  • Observe the call stack at the break point at the constructor, postProcessBeanFactory method, Found BeanPostProcessor initialization in AbstractApplicationContext class registerBeanPostProcessors refresh methods (the beanFactory);

  • PostProcessBeforeInitialization calls in finishBeanFactoryInitialization AbstractApplicationContext classes refresh methods (the beanFactory);

  • FinishBeanFactoryInitialization postProcessAfterInitialization call in class AbstractApplicationContext refresh method (the beanFactory)

conclusion

According to the above debugging analysis, we found that Bean object creation of several key timing code level calls in the refresh method of AbstractApplicationContext classes, visible this method is critical for the Spring IoC container initialization, summary is as follows:

The Spring IoC container initializes the main process

By analysis, the Spring IoC container initialization key link in AbstractApplicationContext# refresh () method, we see the refresh method to overlooking the container to create the body of the process, main process under the specific subprocesses behind us again to discuss it.

BeanFactory creation process

Get the BeanFactory subprocess

BeanDefinition loads the parsing and registration subprocesses

This subprocess involves several key steps as follows

Resource location: The process of locating resources on the BeanDefinition. In plain English, this means finding the XML text that defines the Javabean information

And encapsulate it as a Resource object.

BeanDefinition loading: Represents the user-defined Javabeans as data structures inside the IoC container, the numbers inside the container

The data structure is the BeanDefinition.

Register the BeanDefinition into the IoC container

Process analysis

Step 1: subprocesses entry in AbstractRefreshableApplicationContext# refreshBeanFactory method

Step 2: In turn calls loadBeanDefinitions method of multiple classes – > AbstractXmlApplicationContext – > AbstractBeanDefinitionReader – > XmlBeanDefinitionReader is executed up to the doLoadBeanDefinitions method of XmlBeanDefinitionReader

Step 3: We focused on the registerBeanDefinitions method of the XmlBeanDefinitionReader class. There were several overloaded calls, and we settled on the last one

Here we focus on two areas: A createRederContext method, one is DefaultBeanDefinitionDocumentReader registerBeanDefinitions method of a class, enter the createRederContext method and have a look

As you can see, Spring first completes initialization of the NamespaceHandlerResolver. Let’s go back to the registerBeanDefinitions method and trace it and call it

DefaultBeanDefinitionDocumentReader# registerBeanDefinitions method

Enter the parseBeanDefinitions method

Enter the parseDefaultElement method

At this point, the registration process is over. We find that the so-called registration is to encapsulate the Bean information defined in the encapsulated XML into a BeanDefinition object and put it into a Map. The BeanFactory organizes these BeanDefinitions in a Map structure.

You can see in DefaultListableBeanFactory the definition of the Map

/** Map of bean definition objects, keyed by bean name. */

private final Map<String, BeanDefinition> beanDefinitionMap = new

ConcurrentHashMap<>(256);

Sequence diagram

Bean creation process

  • Through the analysis of the key time point at the beginning, we know that Bean created subprocess entrance in AbstractApplicationContext# refresh () method of finishBeanFactoryInitialization (the beanFactory)

  • Enter the finishBeanFactoryInitialization

Continue to enter the DefaultListableBeanFactory class preInstantiateSingletons method, we find the code for the following part, see factories Bean or common Bean, finally by getBean method for instance

Following along, we’ll go to the AbstractBeanFactory class’s doGetBean method, which has a lot of code, and we’ll go straight to the core

Then enter the AbstractAutowireCapableBeanFactory class method, find the following code section

Take a look at the doCreateBean method, where we focus on two key areas

1. Create the Bean instance without setting the properties

2. Populate the Bean with properties, call the initialization method, and apply the BeanPostProcessor post-processor

Well, today’s article is here, I hope to help you confused screen!