Summary of Java-Spring IoC Principles

Share a big cow's artificial intelligence tutorial. Zero-based! Easy to understand! Funny and humorous! Hope you join the artificial intelligence team too! Please click http://www.captainbed.net

High-level view of Spring container

When Spring starts, it reads the Bean configuration information provided by the application, and generates a corresponding Bean configuration registry in the Spring container, and then instantiates the Bean based on this registry, and assembles the dependencies between the Beans for the upper application Provide a ready operating environment.

In the figure above, the Bean buffer pool is implemented by HashMap.

Introduction to IoC Containers

Spring describes the dependency relationship between Bean and Bean through a configuration file, instantiates Bean and establishes the dependency relationship between Beans by using the reflection function of Java language. On the basis of completing these low-level tasks, Spring's IoC container also provides advanced services such as Bean instance caching, life cycle management, Bean instance proxy, event publishing, and resource loading.

  • BeanFactory is the infrastructure of the Spring framework, facing Spring itself;
  • ApplicationContext is for developers who use the Spring framework. In almost all applications, we directly use ApplicationContext instead of the underlying BeanFactory.

BeanFactory

BeanFactory architecture:

  • BeanDefinitionRegistry: Each <bean> node element in the Spring configuration file is represented by a BeanDefinition object in the Spring container, which describes the configuration information of the Bean. The BeanDefinitionRegistry interface provides a method to manually register BeanDefinition objects to the container.
  • The BeanFactory interface is at the top of the class structure tree. Its main method is getBean(String beanName). This method returns a Bean with a specific name from the container. The functions of the BeanFactory are continuously expanded through other interfaces:
  • ListableBeanFactory : This interface defines several methods for accessing the basic information of the Bean in the container, such as checking the number of Beans, obtaining the configuration name of a certain type of Bean, and checking whether a certain Bean is included in the container;
  • HierarchicalBeanFactory : The interface of the parent-child cascading IoC container, the child container can access the parent container through the interface method; through the HierarchicalBeanFactory interface, Spring's IoC container can establish a parent-child hierarchical association container system, the child container can access the Bean in the parent container, but the parent container Cannot access the bean of the child container. Spring uses parent-child containers to achieve many functions. For example, in Spring MVC, the presentation layer bean is located in a child container, and the business layer and persistence layer beans are located in the parent container. In this way, the presentation layer Bean can refer to the business layer and the persistence layer Bean, while the business layer and the persistence layer Bean cannot see the presentation layer Bean.
  • ConfigurableBeanFactory : is an important interface that enhances the customizability of the IoC container. It defines methods for setting the class loader, property editor, container initialization post processor, etc.;
  • AutowireCapableBeanFactory : defines a method to automatically assemble the Bean in the container according to certain rules (such as matching by name, matching by type, etc.);
  • SingletonBeanRegistry : defines a method that allows single-instance Beans to be registered with the container during runtime;

example:

Use the Spring configuration file to provide configuration information for Car: beans.xml:

<?xml version="1.0" encoding="UTF-8" ?> 
<beans xmlns="Index of /schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="Index of /schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
    
    <bean id="car1" class="com.baobaotao.Car" 
        p:brand="红旗CA72" 
        p:color="黑色" 
        p:maxSpeed="200" /> 
</beans>

Load the configuration file through BeanFactory and start the Spring IoC container:

public class BeanFactoryTest { 
    public static void main(String[] args) throws Throwable{
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource res = resolver.getResource("classpath:com/baobaotao/beanfactory/beans.xml"); 
        BeanFactory bf = new XmlBeanFactory(res);
        System.out.println("init BeanFactory.");
        Car car = bf.getBean("car",Car.class);
        System.out.println("car bean is ready for use!");
}
  • XmlBeanFactory loads Spring configuration information through Resource and starts the IoC container, and then the Bean can be obtained from the IoC container through the getBean(beanName) method of BeanFactory. When the IoC container is started through BeanFactory, the Bean defined in the configuration file is not initialized, and the initialization action occurs at the first call.
  • For Singleton Beans, BeanFactory will cache the Bean instance, so the second use of getBean() to get the Bean will directly get the Bean instance from the cache of the IoC container. Spring provides a cache for single-instance Bean in the DefaultSingletonBeanRegistry class. It is a cache implemented with HashMap. Single-instance Beans are stored in this HashMap with beanName as the key.
  • It is worth mentioning that when initializing the BeanFactory, a logging framework must be provided for it, such as using Log4J, that is, the Log4J configuration file is provided under the classpath, so that the Spring container will not report an error when it is started.

ApplicationContext

ApplicationContext is derived from BeanFactory and provides more practical application-oriented functions.

In BeanFactory, many functions need to be implemented programmatically, while in ApplicationContext, they can be implemented through configuration.

ApplicationContext inherits the HierarchicalBeanFactory and ListableBeanFactory interfaces. On this basis, it also extends the functions of BeanFactory through a number of other interfaces:

  • ClassPathXmlApplicationContext: Load the configuration file from the classpath by default
  • FileSystemXmlApplicationContext: Load the configuration file from the file system by default
  • ApplicationEventPublisher: Let the container have the function of publishing application context events, including container startup events, shutdown events, etc. Beans that implement the ApplicationListener event monitoring interface can receive container events and respond to the events. In the ApplicationContext abstract implementation class AbstractApplicationContext, we can find that there is an ApplicationEventMulticaster, which is responsible for saving all listeners so that they can be notified when the container generates context events.
  • MessageSource: Provides the function of i18n internationalized message access for applications;
  • ResourcePatternResolver: All ApplicationContext implementation classes have implemented functions similar to PathMatchingResourcePatternResolver, and Spring configuration files can be loaded through the prefixed Ant-style resource file path.
  • LifeCycle: This interface was added by Spring 2.0. The interface provides two methods, start() and stop(), which are mainly used to control asynchronous processing. In specific use, this interface is implemented by both ApplicationContext and specific Beans. ApplicationContext will pass the start/stop information to all beans in the container that implement this interface to achieve the purpose of managing and controlling JMX and task scheduling.
  • ConfigurableApplicationContext extends ApplicationContext. It adds two new main methods: refresh() and close(), allowing ApplicationContext to start, refresh, and close the application context. When the application context is closed, call refresh() to start the application context. In the already started state, call refresh() to clear the cache and reload the configuration information, and call close() to close the application context. These interface methods bring convenience to the control and management of the container, but as developers, we don't need to care too much about these methods.

use:

If the configuration file is placed in the classpath, users can use ClassPathXmlApplicationContext first to implement the class:

ApplicationContext ctx = new ClassPathXmlApplicationContext("com/baobaotao/context/beans.xml");

If the configuration file is placed in the path of the file system, you can give priority to using the FileSystemXmlApplicationContext implementation class:

ApplicationContext ctx = new FileSystemXmlApplicationContext("com/baobaotao/context/beans.xml");

Spring 3.0 supports a configuration method based on class annotations. The main function comes from a sub-project of Spring called JavaConfig. Currently, JavaConfig has been upgraded to a part of Spring's core framework.

ApplicationContext instantiates all single-instance Beans when initializing the application context.

WebApplicationContext

WebApplication system architecture:

WebApplicationContext is specially prepared for Web applications, it allows the configuration file to be loaded from the path relative to the Web root directory to complete the initialization work. The ServletContext reference can be obtained from the WebApplicationContext, and the entire Web application context object will be placed as an attribute in the ServletContext so that the Web application environment can access the Spring application context. WebApplicationContext defines a constant ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE. When the context is started, the WebApplicationContext instance is placed in the attribute list of ServletContext with this as the key, so we can directly obtain the WebApplicationContext from the Web container through the following statement:

WebApplicationContext wac = (WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

Context integration of Spring and Web applications:

The initialization method of WebApplicationContext: WebApplicationContext needs an instance of ServletContext, which can only complete the startup work under the premise of having a Web container. You can configure a self-starting Servlet or define a Web container listener (ServletContextListener) in web.xml, and you can start the Spring Web application context with either of these. Spring provides Servlet and Web container listener for starting WebApplicationContext respectively:

  • org.springframework.web.context.ContextLoaderServlet
  • org.springframework.web.context.ContextLoaderListener

Because WebApplicationContext needs to use the logging function, for example, the logging framework uses Log4J, the user can put the configuration file of Log4J under the class path WEB-INF/classes, then the Log4J engine can be started smoothly. If the Log4J configuration file is placed in another location, the user must also specify the location of the Log4J configuration file in web.xml.

Bean's life cycle

1. When the caller requests a certain Bean from the container through getBean(beanName), if the container registers the org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor interface, before instantiating the Bean, the postProcessBeforeInstantiation() method of the interface will be called;

2. According to the configuration, call the Bean constructor or factory method to instantiate the Bean;

3. If the container has registered the InstantiationAwareBeanPostProcessor interface, after instantiating the Bean, call the postProcessAfterInstantiation() method of the interface, where you can "dress up" the instantiated objects;

4. If the Bean is configured with property information, the container sets the configuration value to the corresponding property of the Bean in this step, but before setting each property, it will first call the postProcessPropertyValues() method of the InstantiationAwareBeanPostProcessor interface;

5. Call the attribute setting method of Bean to set the attribute value;

6. If the Bean implements the org.springframework.beans.factory.BeanNameAware interface, the setBeanName() interface method will be called to set the corresponding name of the Bean in the configuration file to the Bean;

7. If the Bean implements the org.springframework.beans.factory.BeanFactoryAware interface, the setBeanFactory() interface method will be called to set the BeanFactory container instance to the Bean;

8. If the BeanFactory is equipped with the org.springframework.beans.factory.config.BeanPostProcessor post processor, it will call the Object postProcessBeforeInitialization(Object bean, String beanName) interface method of the BeanPostProcessor to process the Bean. The input parameter bean is the Bean currently being processed, and beanName is the configuration name of the current Bean, and the returned object is the processed Bean. Users can use this method to perform special processing on certain Beans, or even change the behavior of Beans. BeanPostProcessor occupies an important position in the Spring framework and provides the container with an entry point for subsequent processing of the Bean. The various features provided by the Spring container "Magic functions" (such as AOP, dynamic proxy, etc.) are implemented through BeanPostProcessor;

9. If the Bean implements the InitializingBean interface, the afterPropertiesSet() method of the interface will be called;

10. If an initialization method is defined in <bean> through the init-method attribute, this method will be executed;

11. The BeanPostProcessor post processor defines two methods: one is postProcessBeforeInitialization() called in step 8; the other is the Object postProcessAfterInitialization(Object bean, String beanName) method, which is called at this time, and the container gets to process the Bean again Deal with

12. If the scope of the Bean is specified as scope="prototype" in <bean>, the Bean is returned to the caller, and the caller is responsible for the management of the subsequent life of the Bean. Spring no longer manages the life cycle of the Bean. If the scope is set to scope="singleton", put the Bean into the buffer pool of the Spring IoC container, and return the Bean reference to the caller, and Spring will continue to perform subsequent life management on these Beans;

13. For beans with scope="singleton", when the container is closed, Spring will trigger the subsequent life cycle management of the Bean. First, if the Bean implements the DisposableBean interface, the afterPropertiesSet() method of the interface will be called, which can be written and released here Operations such as resources, recording logs, etc.;

14. For beans with scope="singleton", if the destroy-method attribute of <bean> specifies the destruction method of the Bean, Spring will execute this method of the Bean to complete the release of Bean resources and other operations.

These methods can be roughly divided into three categories:

  • Bean's own methods : such as calling the Bean constructor to instantiate the Bean, calling Setter to set the attribute value of the Bean and the methods specified by the init-method and destroy-method of <bean>;
  • Bean-level life cycle interface methods : such as BeanNameAware, BeanFactoryAware, InitializingBean and DisposableBean, these interface methods are directly implemented by the Bean class;
  • Container-level life cycle interface methods : The steps with "★" in the above figure are implemented by the InstantiationAwareBean PostProcessor and BeanPostProcessor interfaces, and their implementation classes are generally called "post processors". Post-processor interfaces are generally not implemented by the Bean itself. They are independent of the Bean. The implementation class is registered in the Spring container in the form of a container attachment and pre-identified by the Spring container through interface reflection. When the Spring container creates any Bean, these post-processors will take effect, so the impact of these post-processors is global. Of course, the user can program the post processor reasonably so that it can only process the beans of interest.

Another biggest difference between ApplicationContext and BeanFactory is : ApplicationContext will use Java reflection mechanism to automatically identify the BeanPostProcessor, InstantiationAwareBeanPostProcessor and BeanFactoryPostProcessor defined in the configuration file, and automatically register them in the application context; while the latter needs to be manually in the code Call the addBeanPostProcessor() method to register. This is one of the reasons why we generally use ApplicationContext and seldom use BeanFactory in application development.

IOC container working mechanism

Container startup process

The startup process of Spring container and SpringMVC container in web environment:

  1. First, for a web application, it is deployed in a web container, and the web container provides a global context environment. This context is ServletContext, which provides a host environment for the following spring IoC container;
  2. Secondly, there will be contextLoaderListener (or ContextLoaderServlet) in web.xml. When the web container starts, it will trigger the container initialization event. At this time, the contextLoaderListener will listen to this event, and its contextInitialized method will be called. In this method, spring will initialize a startup context. This context is called the root context, which is WebApplicationContext. , This is an interface class, to be precise, its actual implementation class is XmlWebApplicationContext. This is the spring IoC container, and the configuration of the corresponding Bean definition is specified by the context-param tag in web.xml. After this IoC container is initialized, the spring container uses WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE as the attribute Key and stores it in the ServletContext for easy access;
  3. Third, after the contextLoaderListener is initialized, the Servlet configured in web.xml is initialized. This servlet can be configured with multiple. Take the most common DispatcherServlet as an example (Spring MVC). This servlet is actually a standard front controller. Used to forward, match, and process each servlet request. When the DispatcherServlet context is initialized, it will establish its own IoC context container to hold spring mvc-related beans. The default implementation class of the context held by this servlet is also XmlWebApplicationContext. When establishing DispatcherServlet's own IoC context, WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE will be used to obtain the previous root context (ie WebApplicationContext) from the ServletContext as the parent context of its own context (that is, the XmlWebApplicationContext initialized in step 2 as its parent container). After having this parent context, initialize the context it holds (this DispatcherServlet initializes its own context can be seen in its initStrategies method, the general job is to initialize the processor mapping, view resolution, etc.). After initialization, spring uses the attribute related to the servlet name (here is not simply the servlet name Key, but through some conversion) as the attribute Key, and also stores it in the ServletContext for subsequent use. In this way, each servlet holds its own context, that is, has its own independent bean space, and each servlet shares the same beans, that is, those beans defined by the root context.

Bean loading process

The brilliance of Spring is that it uses many interfaces to depict the blueprint of all the devices, build the framework of Spring, and then through the inheritance system layer by layer deduction, continuous enrichment, and finally make Spring a complete framework with flesh and blood. Therefore, when viewing the source code of the Spring framework, there are two clearly visible contexts:
1) The interface layer describes the important components of the container and the cooperation relationship between the components;
2) The inheritance system gradually realizes the functions of the components.

The interface layer clearly outlines the high-level functions of the Spring framework, and the framework is ready to emerge. With the abstract description of the interface layer, not only Spring itself can provide specific implementations, but any third-party organization can also provide different implementations. It can be said that Spring's perfect interface layer ensures the scalability of the framework. The gradual expansion of the vertical inheritance system realizes the functions of the framework step by step. This implementation scheme ensures that the framework functions will not accumulate on certain classes, causing excessive code logic load, and the complexity of the framework is perfectly decomposed opened.

Spring components can be divided into two categories according to their roles:

1) Material components : Resource, BeanDefinition, PropertyEditor and the final Bean, etc., which are processed and consumed components in the processing flow, just like the processed materials on the assembly line;

  • BeanDefinition: Spring converts the <bean> configuration information in the configuration file into the internal representation of the container through BeanDefinition, and registers these BeanDefinitions in the BeanDefinitionRegistry. The subsequent operations of the Spring container directly read the configuration information from the BeanDefinitionRegistry.

2) Processing equipment components : Components such as ResourceLoader, BeanDefinitionReader, BeanFactoryPostProcessor, InstantiationStrategy, and BeanWrapper are processing equipment in different links of the assembly line to process the material components.

  • InstantiationStrategy: Responsible for instantiation of Bean operations, equivalent to the function of new in the Java language, and will not participate in the configuration of Bean properties. The attribute filling work is left to the completion of BeanWrapper.
  • BeanWrapper: inherits the PropertyAccessor and PropertyEditorRegistry interfaces. BeanWrapperImpl encapsulates two types of components: (1) the encapsulated target Bean (2) a set of property editors for setting Bean properties; it has a triple identity: (1) Bean wrapper ( 2) Property accessor (3) Property editor registry. PropertyAccessor: Defines various methods for accessing Bean properties. PropertyEditorRegistry: The registry of the property editor.

This figure describes the Spring container from loading the configuration file to creating a complete Bean workflow:

1. ResourceLoader loads Spring configuration information from the storage medium and uses Resource to represent the resources of this configuration file;

2. BeanDefinitionReader reads the configuration file resource pointed to by Resource, and then parses the configuration file. Each <bean> in the configuration file is parsed into a BeanDefinition object and saved in the BeanDefinitionRegistry;

3. The container scans the BeanDefinition in the BeanDefinitionRegistry, uses Java's reflection mechanism to automatically identify the beans of the Bean factory post-processing processor (implementing the BeanFactoryPostProcessor interface), and then calls these Bean factory post-processors to process the BeanDefinition in the BeanDefinitionRegistry. Mainly complete the following two tasks:

  • 1) Analyze the <bean> element tags that use placeholders to get the final configuration value, which means that some semi-finished BeanDefinition objects are processed and the finished BeanDefinition objects are obtained;
  • 2) Scan the BeanDefinition in the BeanDefinitionRegistry, find out all the Beans of the property editor (Beans that implement the java.beans.PropertyEditor interface) through the Java reflection mechanism, and automatically register them in the property editor registry of the Spring container ( PropertyEditorRegistry);

4. The Spring container takes out the processed BeanDefinition from the BeanDefinitionRegistry and calls InstantiationStrategy to start the work of Bean instantiation;

5. When instantiating the Bean, the Spring container uses the BeanWrapper to encapsulate the Bean. The BeanWrapper provides many methods to manipulate the Bean with the Java reflection mechanism. It will combine the BeanDefinition of the Bean and the property editor in the container to complete the setting of the Bean properties;

6. Use the Bean post processor registered in the container (the Bean that implements the BeanPostProcessor interface) to perform subsequent processing on the Bean that has completed the property setting work, and directly assemble a ready Bean.

to sum up

  • Spring IOC container mainly has BeanFactory at the bottom of the inheritance system, high-level ApplicationContext and WebApplicationContext
  • Bean has its own life cycle
  • Container startup principle: IOC container of Spring application is started and loaded through Tomcat Servlet or Listener monitoring; Spring MVC container is loaded by DispatchServlet as entrance; Spring container is the parent container of Spring MVC container
  • The principle of container loading Bean:
  1. BeanDefinitionReader reads the configuration file resource pointed to by Resource, and then parses the configuration file. Each <bean> in the configuration file is parsed into a BeanDefinition object and saved in the BeanDefinitionRegistry;
  2. The container scans the BeanDefinition in the BeanDefinitionRegistry; calls InstantiationStrategy to instantiate Bean; uses BeanWrapper to complete the setting of Bean properties;
  3. Singleton Bean Cache Pool: Spring provides a cache for single-instance Beans in the DefaultSingletonBeanRegistry class. It is a cache implemented with HashMap. Single-instance Beans are stored in this HashMap with beanName as the key.

Guess you like

Origin blog.csdn.net/chimomo/article/details/110874622