“This is the second day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

preface

Welcome to our GitHub repository Star: github.com/bin39232820… The best time to plant a tree was ten years ago, followed by now

omg

Some of the previous articles have nothing to say about some knowledge points related to Spring. This is not to say that they are not very good, but that they just talk about a certain knowledge point and are not so systematic. Next, we will talk about the system, of course, we can learn from others.

Several core concepts in Spring

The IoC and DI

  • IoC (Inversion of Control) This is not a new technology, but a design idea from Spring.
    • In traditional programming, we create objects directly within the object through new, it is the program to create dependent objects; In Spring, there is a special container to create and manage these objects and inject other objects that they depend on into them. This container is commonly referred to as the IoC container.

The creation and destruction of all classes is controlled by Spring, which means that it is not the reference object that controls the life cycle of an object, but Spring. For a specific object, it used to control other objects, but now all objects are controlled by Spring, so this is called inversion of control.

  • DI (Dependency Injection) was proposed by Martin Fowler. It can be argued that IoC and DI are two different descriptions of the same concept.

    • Dependency injection means that the dependencies between components are determined by the container at run time. Figuratively speaking, the container dynamically injects a dependency into the component. The purpose of dependency injection is not to bring more functions to the software system, but to increase the frequency of component reuse and build a flexible and extensible platform for the system.

    Through the dependency injection mechanism, we can specify the resources needed by the target and complete our business logic through simple configuration without any code, regardless of where the specific resources come from and who implements them.

bean

Official concept: In Spring, the objects that make up the backbone of an application and are managed by the Spring IoC container are called beans. A bean is an object instantiated, assembled, and managed by the Spring IoC container.

In plain English: Beans can be thought of as abstractions of Java object instances that we want to inject into the Spring IoC container.

We often use the @Service annotation on a Service and then inject it through the @Autowire annotation in the class where the Service is to be used. The Service is a bean. In this case, the @service annotation tells the IoC container: This class you need to help me create and manage; The @Autowire annotation tells the IoC container: I need to rely on this class and you need to inject it for me.

The difference between Java objects and Spring Beans

  • The first is that a SpringBean must be a Java object, but a Java object does not have to be a SpringBean
  • The second is that a SpringBean is generated by a Java object and then, through a series of Spring operations, becomes a SpringBean

BeanDefinition

Once you understand beans, BeanDefinition is easy to understand. A BeanDefinition is a bean definition that stores all of the bean’s attribute method definitions.

The BeanFactory and ApplicationContext

  • BeanFactory: Basic IoC container that provides full IoC service support.

  • ApplicationContext: a subinterface to the BeanFactory, built on top of the BeanFactory, is a relatively high-level IoC container implementation. Contains all the functionality of the BeanFactory, as well as other advanced features such as event publishing, international information support, uniform resource loading policies, and more. Normally, we use the ApplicationContext.

FactoryBean

Typically, we leave bean creation and management to the Spring IoC container, which instantiates the bean using the class specified by the bean’s class attribute.

But if we want to implement bean creation ourselves, can we? The answer is yes, and factoryBeans fulfill this requirement.

A FactoryBean is a special kind of bean. It is a FactoryBean that can create bean instances. If a class implements the FactoryBean interface, it can define its own methods for creating instance objects by implementing its getObject() method.

FactoryBean may not be used or noticed in normal development, but it is widely used, especially in middleware. If you look at the source code of middleware, you will see FactoryBean.

The core processes

Container build startup entry

There are many different entry points for container build startup, in the form of common web.xml configuration.

First, we configure the ContextLoaderListener listener in web. XML. When Tomcat starts, the contextInitialized method of the ContextLoaderListener is fired. Thus the IoC construction process begins.

Another commonly used parameter is contextConfigLocation, which specifies the path to the Spring configuration file.

<? The XML version = "1.0" encoding = "utf-8"? > < web - app version = "2.5" XMLNS = "http://java.sun.com/xml/ns/javaee" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>open-joonwhee-service WAR</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:config/spring/appcontext-*.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>Copy the code

So let’s look at this method

  • What did the following step by step, we analyze initWebApplicationContext class.
    1. Make sure that only one ContextLoader* related configuration exists in the initialization context, otherwise the exception is thrown

2. Print related logs and calculate the start time.Copy the code

3. Store the context in the local instance variable to ensure that it is available when the ServletContext is closed. Which createWebApplicationContext method is instantiated the roots of the loader WebApplicationContext, if you specify a default context class or custom context class “. The default context is xmlWebApplicationContext.4. To determine whether application context belongs to ConfigurableWebApplicationContext instance. The default xmlWebApplicationContext belongs to ConfigurableWebApplicationContext instance. If the application context does not take effect, check whether the parent context is set for the application context. The loadParentContext method’s main function is “a template method with a default implementation (possibly overridden by subclasses) to load or get an ApplicationContext instance that will be used as the parent of the root WebApplicationContext.”ConfigureAndRefreshWebApplicationContext is the main purpose of “the contextConfigLocation path of access to the web. In the XML configuration, application access path, the spring related XML configuration file path, And refresh the current WebApplicationContext configuration.” Finally, the context object is placed in the servlet context parameter. This step is often referred to as the Spring container startup process, but I won’t go into details here, but into tens of thousands of words 5. Get the current thread’s classloader, and if the ContextLoader is the same as the current thread’s classloader, apply the context object to currentContext.

ApplicationContext is configured before refreshing

There are a few pre-operations before we start flushing the container.

  • Identify the container to use, usually using: XmlWebApplicationContext, if is to use Spring to Boot, is AnnotationConfigApplicationContext commonly, but it is a huge difference, Eventually inherit AbstractApplicationContext, core logic are also in AbstractApplicationContext implementation.
  • Provides an opportunity for developers to initialize the ApplicationContext as follows

Example: ApplicationContextInitializer extended use

Create a ApplicationContextInitializer interface implementation class, such as the following SpringApplicationContextInitializer, and in the initialize method has its own logic operation, such as: Add listeners and Add BeanFactoryPostProcessor.

package com.joonwhee.open.spring; import com.joonwhee.open.listener.EarlyListener; import com.joonwhee.open.processor.MyBeanFactoryPostProcessor; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; /** */ public class SpringApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void The initialize (ConfigurableApplicationContext applicationContext) {/ / own logic implementation / / example 1: EarlyListener = new EarlyListener(); applicationContext.addApplicationListener(earlyListener); // Example 2: By adding the spring BeanFactoryPostProcessor hard-coded way MyBeanFactoryPostProcessor MyBeanFactoryPostProcessor = new MyBeanFactoryPostProcessor(); applicationContext.addBeanFactoryPostProcessor(myBeanFactoryPostProcessor); }}Copy the code

In the web. In the XML, define contextInitializerClasses or globalInitializerClasses parameters, parameter values for SpringApplicationContextInitializer the full path.

Initialize the BeanFactory and load the Bean definition

1, create a new the BeanFactory, DefaultListableBeanFactory on by default.

2. Read the Spring configuration file according to the path specified by contextConfigLocation in web. XML and encapsulate it as Resource.

Load the XML configuration file according to Resource and parse it into a Document object.

4. Start with the root node and iterate through the nodes in the parse Document.

4.1. For nodes in the default namespace: first parse the bean node content and encapsulate it into BeanDefinition, and then put beanName and BeanDefinition into the cache of BeanFactory for subsequent bean instance creation.

The default namespace: www.springframework.org/schema/bean…

The trigger spring BeanFactoryPostProcessor

All spring BeanFactoryPostProcessor instantiation and calls, including its subclasses BeanDefinitionRegistryPostProcessor.

The BeanFactoryPostProcessor interface is the extension point exposed when Spring initializes the BeanFactory. The Spring IoC container allows the BeanFactoryPostProcessor to read the bean definition and modify it before the container instantiates any bean.

BeanDefinitionRegistryPostProcessor inherited from spring BeanFactoryPostProcessor, a higher priority than spring BeanFactoryPostProcessor, It is used to register bean definitions before the normal BeanFactoryPostProcessor is activated. In particular, you can register by BeanDefinitionRegistryPostProcessor some conventional spring BeanFactoryPostProcessor, Because at this point all the normal BeanFactoryPostProcessor has yet to be processed.

Note: the side of the “normal” spring BeanFactoryPostProcessor with BeanDefinitionRegistryPostProcessor is mainly used to distinguish.

Example: BeanFactoryPostProcessor extension use

  1. Create a spring BeanFactoryPostProcessor interface implementation class, such as the following MyBeanFactoryPostProcessor, and in postProcessBeanFactory approach has its own logic operation. For example, scan a package path and register all classes under that package path that use an annotation with Spring.

  2. Register the implementation class with the Spring container, for example using the @Component annotation

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void PostProcessBeanFactory (ConfigurableListableBeanFactory the beanFactory) throws BeansException {/ / see no at this time we can get the beanFactory, You got it, then you can do whatever you want. }}Copy the code

In addition, the MapperScannerConfigurer Mybatis is a typical BeanDefinitionRegistryPostProcessor extended use, interested can look at the source code of this class. The Mapper class is a Spring annotation, not that it implements the hook to inject its beans into the Spring IOC container

Registered BeanPostProcessor

Register all beanPostProcessors and load all classes that implement the BeanPostProcessor interface into the BeanFactory.

The BeanPostProcessor interface is an extension point exposed when Spring initializes beans. The Spring IoC container allows the BeanPostProcessor to add its own logical processing before and after the container initializes beans. In this case, we just register the BeanFactory, which is called when the bean is initialized.

public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object PostProcessBeforeInitialization (Object beans, String beanName) throws BeansException {/ / own logic return li beans; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// Own logical return bean; }}Copy the code

Instantiate all remaining non-lazy-loaded singleton beans

1. Iterate over all beanName loaded into the cache, triggering instantiation of all remaining non-lazy-loaded singleton beans.

2. First try to fetch it from the cache by beanName. If it exists, skip the instantiation process. Otherwise, instantiate the bean.

3. Create the bean instance using the constructor according to the BeanDefinition.

4. Populate the bean instance properties according to BeanDefinition.

Perform the initialization of the bean instance.

5.1 trigger the Aware method.

5.2, trigger a BeanPostProcessor postProcessBeforeInitialization method.

5.3. If the bean implements the InitializingBean interface, the afterPropertiesSet() method is fired.

5.4. If the bean has the init-method property set, the method specified by init-method is triggered.

5.5, trigger a BeanPostProcessor postProcessAfterInitialization method.

6. Place the created bean instance in the cache for later use. (More complicated if it’s a circular dependency)

Complete the Spring container context creation

At the end

This is a general process of Spring IOC. We will explain the details one by one later.

Daily for praise

Ok, everybody, that’s all for this article, you can see people here, they are real fans.

Creation is not easy, your support and recognition, is the biggest motivation for my creation, we will see in the next article

Six pulse excalibur | article “original” if there are any errors in this blog, please give criticisms, be obliged!