Spring source code analysis

Through the previous study, we have learned how the primary container of spring is initialized, but compared with the unfamiliar XmlBeanFactory, ApplicationContext is obviously more familiar to everyone. The spring advanced container ApplicationContext contains all the things in the primary container XmlBeanFactory. Based on the primary container, ApplicationContext extends many advanced features and provides us with many function extension points. Through these function extension points, we can transform the functions of the spring framework to be more satisfied with my actual business scenario. Starting from this article, let's explore how spring's advanced container ApplicationContext is initialized.

Let's first look at the simple and practical ApplicationContext:
It can be seen that the xml file is also parsed. If I use ApplicationContext to parse, i.e. replace the previous XmlBeanFactory with the implementation class CalssPathXmlApplicationContext of ApplicationContext. The execution result is the same as that of XmlBeanFactory. There are many implementation classes of ApplicationContext interface. We use ClassPathXmlApplicationContext as the entry of ApplicationContext to initialize source code analysis.

Through the name of ClassPathXmlApplicationContext, we can know that it loads and parses ApplicationContext from the classpath path XML.
Let's go to the ClassPathXmlApplicationContext method and have a look:

It can be seen that in the construction method of classPathXmlApplicationContextd, the xml file name will be encapsulated into a String type array, and then the value of parameter refresh true and parent value null will be taken to continue to call another overloaded construction method of ClassPathXmlApplicationContext.
Let's look at the overload construction method of ClassPathXmlApplicationContext:





As you can see, first use the super method to call the constructor of the parent class. We follow the parent class AbstractApplicationContext layer by layer and find that there are two methods:
Let's go to this() method to see:

This should be to initialize a member variable resourcePatternResolver. What can the getResourcePatternResolver method get? Let's go in and have a look:

It can be seen that the member variable resourcePatternResolver is initialized with the type of PathMatchingResourcePatternResolver. According to the name, we can infer that the PathMatchingResourcePatternResolver should be a resource parser that matches the path and a component that obtains xml file resources.

We are looking at the setParent method:

You can see that the parameter parent is passed into the setParent method. We know that the parent parameter is a null value.

Back to the ClassPathXmlApplicationContext constructor:

applicationContext. The XML file is encapsulated as a String array as a parameter and then called method setConfigLocations.
Let's take a look at this setconfiglocacations method:

As you can see, in the setConfigLocations method, a new string array configLocations is built through the parameter locations we passed in to store the parsed xml file path.
How will this resolvePath be parsed? Let's take a look:

Let's go to the method resolveRequiredPlaceholders to see:

That is, if there is a placeholder ${} in the xml path parameter path we passed in, the method resolveRequiredPlaceholders can resolve the placeholder. Moreover, if there is a ${} placeholder in the xml path, but there is no corresponding default attribute value, an error will be reported.

Up to now, we have seen that spring will make some preparations for the xml path we set in, such as parsing some placeholders in the path, but when will the xml file be loaded and parsed?
Now let's look at the ClassPathXMLApplicationContext construction method:

As we have seen earlier, the value of the parameter refresh is true, so the refresh method will be called. What exactly is the refresh method doing?
Let's take a look at this refresh method:

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// Initialize context information
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// Initialize the primary container BeanFactory and parse the xml file
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// Do some preparatory work for the spring container beanFactory
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// Empty implementation, leaving subclasses to expand the implementation. It is used to register special postprocessors to load special bean s
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// Execute BeanFactory, which is the post processor of Spring container level
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// In the spring container, register the post processor of the bean
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// In the spring container, initialize the message source MessageSource
				initMessageSource();

				// Initialize event multicaster for this context.
				// spring container, initializing event broadcaster
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// Empty implementation, leaving subclasses to expand implementation
				// It is used to do some other work to initialize the bean before instantiating the bean
				onRefresh();
			
				// Check for listener beans and register them.
				// Initialize the various listeners in the spring container
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// Pre instantiate those singleton bean s that are not loaded late
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// Initialize the lifecycle processor and the corresponding event notification
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

You can see. The core logic of container ApplicationContext initialization is in refresh. In the following articles, I expand around the refresh method.

Keywords: Spring Microservices eureka

Added by ShaolinWood on Sun, 06 Mar 2022 09:58:46 +0200