Alias interprets springboot 2.6 0 source code: start the refresh application context of process analysis

1, Background

    in the previous article, we interpreted preparing the application context. In this article, we mainly interpreted refreshing the application context (first). As usual, we still review the overall process started, so that we can not get lost.

1.1. Overall process of run method

  the specific path of the class where the next few methods are located: org springframework. boot. SpringApplication

	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}
	
	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

	public ConfigurableApplicationContext run(String... args) {
		// 1. Create and start the timing monitoring class
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		
		// 2. Initialize startup context, initialize application context
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		
		// 3. Set the headless attribute: "java.awt.headless". The default value is: true (there is no graphical interface)
		configureHeadlessProperty();
		
		// 4. Create all Spring run listeners and publish application startup events
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			// 5. Initialize default application parameter class
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			
			// 6. Prepare the Spring environment according to the running listener and application parameters
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
			
			// 7. Create a Banner and print
			Banner printedBanner = printBanner(environment);
			
			// 8. Create application context
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			
			// 9. Prepare application context
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			
			// 10. Refresh application context
			refreshContext(context);
			
			// 11. Post processing of application context refresh
			afterRefresh(context, applicationArguments);
			
			// 12. Stop timing monitoring class
			stopWatch.stop();
			
			// 13. The output log records the name and time of the main execution class
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			
			// 14. Publish application context startup completion event
			listeners.started(context);
			
			// 15. Execute all Runner
			callRunners(context, applicationArguments);
		} catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			// 16. Publish application context ready event
			listeners.running(context);
		} catch (Throwable ex) {
			// 17. Error handling
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		// 18. Return application context
		return context;
	}

1.2. Overall calling process of refresh

  the specific path of the class where this method is located: org springframework. boot. SpringApplication

	private void refreshContext(ConfigurableApplicationContext context) {
		if (this.registerShutdownHook) {
			// Another listener ApplicationContextClosedListener is added. In the previous article, we said that there are 11 listeners ready to refresh, and now there are 12
			shutdownHook.registerApplicationContext(context);
		}
		refresh(context);
	}

	protected void refresh(ConfigurableApplicationContext applicationContext) {
		// The final implementation is the refresh method of AbstractApplicationContext
		applicationContext.refresh();
	}

  the specific path of the class where this method is located: org springframework. context. support. AbstractApplicationContext

@Override
	public void refresh() throws BeansException, IllegalStateException {
		// Refresh by synchronization
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refresh
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of bean factories in context subclasses
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Call the factory processor registered as a bean in the context
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register the BeanPostProcessor created by the intercepting bean
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize the message source for this context, that is, register the DelegatingMessageSource
				initMessageSource();

				// Initialize the event multicast for this context
				initApplicationEventMulticaster();

				// Initialize other special bean s in a specific context subclass, such as creating a built-in Servlet container
				onRefresh();

				// Check listener bean s and register them
				registerListeners();

				// Instantiate all remaining (non lazy initialization) singletons
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish the corresponding event
				finishRefresh();
			} catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);
				}

				// Destroy the created singleton to avoid dangling resources
				destroyBeans();
				
				// Reset "active" flag
				cancelRefresh(ex);
				// Propagate exception to caller
				throw ex;
			} finally {
				//Reset the common introspective cache in the Spring core, because we may no longer need the metadata of the singleton bean...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}
  • Synchronous operation
  • Prepare this context for refresh
  • Tell the subclass to refresh the internal bean factory
  • Prepare the bean factory for use in this context
  • Allows post-processing of bean factories in context subclasses
  • Call the factory processor registered as a bean in the context
  • Register the BeanPostProcessor created by the intercepting bean
  • Initialize the message source for this context, that is, register the DelegatingMessageSource
  • Initialize event multicast for this context
  • Initializes other special bean s in subclasses of a specific context
  • Check listener bean s and register them
  • Instantiate all remaining (non lazy initialization) singletons
  • Publish corresponding events

1.3 scope of interpretation

  this article mainly explains some contents of the refresh() method, that is:

	// Prepare this context for refresh
	prepareRefresh();

	// Tell the subclass to refresh the internal bean factory
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

	// Prepare the bean factory for use in this context
	prepareBeanFactory(beanFactory);
	try {
		// Allows post-processing of bean factories in context subclasses
		postProcessBeanFactory(beanFactory);
		// Omitted later, this is here
	} catch (BeansException ex) {
	
	}finally{
	}

   there are many contents of the whole method. For a more detailed interpretation, we will interpret it in several parts. This paper interprets the context subclass to post process the bean factory.

2, Ready to refresh

2.1. Process for preparing to refresh

  the specific path of the class where this method is located: org springframework. context. support. AbstractApplicationContext

	protected void prepareRefresh() {
		// Record time
		this.startupDate = System.currentTimeMillis();
		// Flag for context closure
		this.closed.set(false);
		// Context switch to active state
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			} else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initializing servlet related attribute sources in context
		// It is implemented by calling the overridden method of the subclass GenericWebApplicationContext
		initPropertySources();

		//Verify that all properties marked "required" are resolvable:
		//See ConfigurablePropertyResolver#setRequiredProperties for details
		getEnvironment().validateRequiredProperties();

		// Store pre refresh application listener
		if (this.earlyApplicationListeners == null) {
			// At this time, there are 12 listeners in the context. For details, see the sources of 11 listeners in my last article and one added in this article
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		} else {
			// Reset the local application listener to the pre refresh state
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Once multicast is available, allow early application events to be published
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
  • Switches the context to the active state
  • Initialize the servlet related attribute source in the context by calling the overridden method of the subclass GenericWebApplicationContext
  • Pre refresh application listener processing
  • Define early ApplicationEvent events

2.2. Initialize servlet related attribute sources in context

  the specific path of the class where this method is located: org springframework. web. context. support. GenericWebApplicationContext

public class GenericWebApplicationContext extends GenericApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource {
	@Override
	protected void initPropertySources() {
		// Get the environment as ApplicationServletEnvironment
		ConfigurableEnvironment env = getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			// ApplicationServletEnvironment inherits the StandardServletEnvironment 
			// The standard servlet environment implements the configurableweb environment
			((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
		}
	}
}

  the specific path of the class where this method is located: org springframework. web. context. support. StandardServletEnvironment

public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
	@Override
	public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
		// For the value of getPropertySources(), please refer to my previous article: starting application environment preparation for process analysis
		WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
	}
}

The structure is roughly as follows:

	ApplicationServletEnvironment {
		activeProfiles=[], 
		defaultProfiles=[default], 
		propertySources=[
			ConfigurationPropertySourcesPropertySource {name='configurationProperties'},
			SimpleCommandLinePropertySource {name='commandLineArgs'}, 
			StubPropertySource {name='servletConfigInitParams'}, 
			StubPropertySource {name='servletContextInitParams'}, 
			PropertiesPropertySource {name='systemProperties'}, 
			OriginAwareSystemEnvironmentPropertySource@1483145520 {name='systemEnvironment'},
			RandomValuePropertySource@1961129028 {name='random'},
			OriginTrackedMapPropertySource@1506938939 {name='Config resource ' }
		]
	}
public abstract class WebApplicationContextUtils {
	public static void initServletPropertySources(MutablePropertySources sources,
			@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {

		Assert.notNull(sources, "'propertySources' must not be null");
		// servletContextInitParams
		String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;
		if (servletContext != null && sources.get(name) instanceof StubPropertySource) {
			sources.replace(name, new ServletContextPropertySource(name, servletContext));
		}
		// servletConfigInitParams
		name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;
		if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {
			sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
		}
	}
}

  servletContext is null, so nothing is done

2.3. Verify the require attribute

public abstract class AbstractEnvironment implements ConfigurableEnvironment {
	private final ConfigurablePropertyResolver propertyResolver;

	@Override
	public void validateRequiredProperties() throws MissingRequiredPropertiesException {
		// The propertyResolver here is PropertySourcesPropertyResolver, which is initialized and assigned when the prepareEnvironment method creates the environment
		this.propertyResolver.validateRequiredProperties();
	}
}

    the propertyResolver here is PropertySourcesPropertyResolver, which is initialized and assigned when the prepareEnvironment method creates the environment. PropertySourcesPropertyResolver inherits the abstract class AbstractPropertyResolver

public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {}

  AbstractPropertyResolver implements the interface ConfigurablePropertyResolver

public abstract class AbstractPropertyResolver implements ConfigurablePropertyResolver {
	private final Set<String> requiredProperties = new LinkedHashSet<>();

	@Override
	public void validateRequiredProperties() {
		MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
		// requiredProperties is empty
		for (String key : this.requiredProperties) {
			if (this.getProperty(key) == null) {
				ex.addMissingRequiredProperty(key);
			}
		}
		if (!ex.getMissingRequiredProperties().isEmpty()) {
			throw ex;
		}
	}
}

2.4 pre refresh application listener

   pre refresh application listeners at this time (12):

  • Internal class Listener of RSocketPortInfoApplicationContextInitializer
  • ServerPortInfoApplicationContextInitializer
  • Internal class of ConditionEvaluationReportLoggingListener ConditionEvaluationReportListener
  • EnvironmentPostProcessorApplicationListener
  • AnsiOutputApplicationListener
  • LoggingApplicationListener
  • BackgroundPreinitializer
  • DelegatingApplicationListener
  • ParentContextCloserApplicationListener
  • ClearCachesApplicationListener
  • FileEncodingApplicationListener
  • The inner class of SpringApplicationShutdownHook is ApplicationContextClosedListener

3, Notify subclasses to refresh internal beanFactory

  the specific path of the class where this method is located: org springframework. context. support. AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		// The returned beanFactory is DefaultListableBeanFactory. For details, see my previous article: start process analysis to create application context
		return getBeanFactory();
	}
}
  • Refresh beanFactory
  • Get the beanFactory. Here you get the DefaultListableBeanFactory

  let's take a look at the specific path of the class where the refreshBeanFactory() method is located: org springframework. web. context. support. GenericWebApplicationContext

public class GenericWebApplicationContext extends GenericApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource {
	@Override
	protected final void refreshBeanFactory() throws IllegalStateException {
		// The refreshed flag here is a refresh flag, which is set to true without refreshing
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		// The obtained context id is application
		// Set the serialization id of beanFactory
		this.beanFactory.setSerializationId(getId());
	}
}

  the specific path of the class where this method is located: org springframework. beans. factory. support. DefaultListableBeanFactory

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
		
	// Sequence factory mapping: key is the serialization id and value is the weak reference object
	private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
			new ConcurrentHashMap<>(8);

	// Serializable Id of this factory for serialization
	@Nullable
	private String serializationId;

	public void setSerializationId(@Nullable String serializationId) {
		if (serializationId != null) {
			// When the serialization id is not empty, the DefaultListableBeanFactory is added to the mapping through a weak reference
			serializableFactories.put(serializationId, new WeakReference<>(this));
		} else if (this.serializationId != null) {
			serializableFactories.remove(this.serializationId);
		}
		// Set application context serialization id (unique)
		this.serializationId = serializationId;
	}
}

4, Prepare beanFactory

4.1. Overall process of preparing beanFactory

  the specific path of the class where this method is located: org springframework. context. support. AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

	private static final boolean shouldIgnoreSpel = SpringProperties.getFlag("spring.spel.ignore");

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the class loader of the context
		beanFactory.setBeanClassLoader(getClassLoader());
		// If you do not configure the property spring spel. Ignore, the default is false, that is, spel is supported
		if (!shouldIgnoreSpel) {
			// Instantiate a standard Bean expression parser, standardbean expressionresolver
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		}
		// Add an attribute registration editor. The registerCustomEditors method of resourceeditorregister is mainly used to register simple and common types of attribute editors
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Add a post processor and configure beanFactory using context callback
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		// Dependency interfaces to ignore when adding dependency checking and autowire. By default, only the BeanFactory interface is ignored
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
		
		// The BeanFactory interface is not registered as a resolvable type in a normal factory
		// Register MessageSource as a bean (and find the automatic connection)
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Registering the early post processor is used to detect internal bean s, such as ApplicationListener
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect LoadTimeWeaver and prepare for weaving (if found)
		if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set up a temporary class loader for type matching
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment bean s
		// If there is no bean with beanName environment in beanFactory, register environment
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		// If there is no bean with beanName systemProperties in beanFactory, register systemProperties
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		// If there is no bean with beanName systemEnvironment in beanFactory, register systemEnvironment
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		// If there is no bean with beanName of applicationStartup in beanFactory, then register applicationStartup
		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
		}
	}
	
}
  • Tell the internal bean factory to use the class loader of the context
  • Instantiate a standard Bean expression parser, standardbean expressionresolver
  • Add a post processor and configure beanFactory using context callback
  • Add property registration editor ResourceEditorRegistrar
  • Dependency interfaces to ignore when adding dependency checking and autowire
  • Register the early post processor to detect internal bean s
  • Detect LoadTimeWeaver and prepare for weaving
  • Register default environment bean s (environment, systemProperties, systemEnvironment, applicationStartup)

4.2,StandardBeanExpressionResolver

  the specific path of the class where this method is located: org springframework. context. expression. StandardBeanExpressionResolver

public class StandardBeanExpressionResolver implements BeanExpressionResolver {

	// Default expression prefix: '#{'
	public static final String DEFAULT_EXPRESSION_PREFIX = "#{";
	// Default expression suffix: '}'
	public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
	private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
	private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;

	public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
		this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
	}
}

   the construction method is to obtain an expression parser SpelExpressionParser, and the construction method of SpelExpressionParser (the main parameter is SpelParserConfiguration) mainly initializes the Spel compilation mode, which mainly consists of three types:

  • SpelCompilerMode.OFF
  • SpelCompilerMode.IMMEDIATE
  • SpelCompilerMode.IMMEDIATE

  in this article, the default spelcompilermode Off. The construction method of SpelParserConfiguration is relatively simple. You can refer to it yourself.

4.3 other brief descriptions

1. The registerCustomEditors method of ResourceEditorRegistrar is mainly used to register simple common types of attribute editors

2. ApplicationListenerDetector: main functions:

  • After bean initialization: if the bean is an instance of ApplicationListener and the bean is a singleton, it will be added to this In applicationlisteners
  • Do something before the Bean is destroyed: if the Bean is an instance of ApplicationListener, it will be deleted from the event broadcaster applicationeventmulticast

3. ApplicationContextAwareProcessor can be used to process the bean object that implements ApplicationContextAware. Its postProcessBeforeInitialization method is the dependency interface to be ignored (see point 4 for details), so it will inject the Aware interface, otherwise it will directly return to the bean

4. Dependency interfaces to ignore (three added when creating application context):

  • org.springframework.context.ApplicationEventPublisherAware (added this time)
  • org.springframework.context.MessageSourceAware (added this time)
  • org.springframework.beans.factory.BeanFactoryAware
  • org.springframework.context.EnvironmentAware (added this time)
  • org.springframework.context.ResourceLoaderAware (added this time)
  • org. springframework. context. Embeddedvalueresolveaware (added this time)
  • org.springframework.context.ApplicationContextAware (added this time)
  • org.springframework.context.ApplicationStartupAware (added this time)
  • org.springframework.beans.factory.BeanNameAware
  • org.springframework.beans.factory.BeanClassLoaderAware

5. The beanFactory interface is not resolvable in an ordinary factory

  • org.springframework.context.ApplicationContext
  • org.springframework.beans.factory.BeanFactory
  • org.springframework.core.io.ResourceLoader
  • org.springframework.context.ApplicationEventPublisher

5, The context subclass post processes the bean factory

  the specific path of the class where this method is located: org springframework. boot. web. servlet. context. AnnotationConfigServletWebServerApplicationContext

public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
		implements AnnotationConfigRegistry {
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.postProcessBeanFactory(beanFactory);
		if (this.basePackages != null && this.basePackages.length > 0) {
			this.scanner.scan(this.basePackages);
		}
		if (!this.annotatedClasses.isEmpty()) {
			this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
		}
	}
}

  the postProcessBeanFactory method of the parent class ServletWebServerApplicationContext is called here.

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
		implements ConfigurableWebServerApplicationContext {
	@Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Add post processor (3 after adding)
		beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
		// Add dependency interface to ignore ()
		beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		// Register web application scope
		registerWebApplicationScopes();
	}
}
  • Add post processor
  • Add dependency interfaces to ignore
  • Register web application scope
public class WebApplicationContextServletContextAwareProcessor extends ServletContextAwareProcessor {

	private final ConfigurableWebApplicationContext webApplicationContext;

	public WebApplicationContextServletContextAwareProcessor(ConfigurableWebApplicationContext webApplicationContext) {
		Assert.notNull(webApplicationContext, "WebApplicationContext must not be null");
		this.webApplicationContext = webApplicationContext;
	}
}

Post processor:

  • ApplicationContextAwareProcessor (added in prepareBeanFactory method)
  • ApplicationListenerDetector (added in prepareBeanFactory method)
  • WebApplicationContextServletContextAwareProcessor (added this time)

Dependency interface to ignore:

  • org.springframework.context.ApplicationEventPublisherAware
  • org.springframework.context.MessageSourceAware
  • org.springframework.web.context.ServletContextAware (added this time)
  • org.springframework.beans.factory.BeanFactoryAware
  • org.springframework.context.EnvironmentAware
  • org.springframework.context.ResourceLoaderAware
  • org.springframework.context.EmbeddedValueResolverAware
  • org.springframework.context.ApplicationContextAware
  • org.springframework.context.ApplicationStartupAware
  • org.springframework.beans.factory.BeanNameAware
  • org.springframework.beans.factory.BeanClassLoaderAware

  about instantiation of existingwebapplicationscope:

	private void registerWebApplicationScopes() {
		ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
		WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
		existingScopes.restore();
	}

	public static class ExistingWebApplicationScopes {

		private static final Set<String> SCOPES;

		static {
			Set<String> scopes = new LinkedHashSet<>();
			scopes.add(WebApplicationContext.SCOPE_REQUEST);
			scopes.add(WebApplicationContext.SCOPE_SESSION);
			SCOPES = Collections.unmodifiableSet(scopes);
		}

		private final ConfigurableListableBeanFactory beanFactory;

		private final Map<String, Scope> scopes = new HashMap<>();

		public ExistingWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
			this.beanFactory = beanFactory;
			for (String scopeName : SCOPES) {
				Scope scope = beanFactory.getRegisteredScope(scopeName);
				if (scope != null) {
					this.scopes.put(scopeName, scope);
				}
			}
		}
	}

  about the registerwebapplicationscope method:

public abstract class WebApplicationContextUtils {
	
	public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
		registerWebApplicationScopes(beanFactory, null);
	}
	
	public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
			@Nullable ServletContext sc) {
		// Register request scope
		beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
		// Register session scope
		beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
		if (sc != null) {
			ServletContextScope appScope = new ServletContextScope(sc);
			beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
			// Register as ServletContext attribute, for ContextCleanupListener to detect it.
			sc.setAttribute(ServletContextScope.class.getName(), appScope);
		}
		// Add a beanFactory interface that is not resolvable in a normal factory
		beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
		beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
		beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
		beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
		if (jsfPresent) {
			FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
		}
	}
}

beanFactory interfaces that are not resolvable in ordinary factories (4 were added before the article):

  • javax.servlet.ServletResponse (added this time)
  • org.springframework.context.ApplicationContext
  • org.springframework.web.context.request.WebRequest (added this time)
  • org.springframework.beans.factory.BeanFactory
  • org.springframework.core.io.ResourceLoader
  • javax.servlet.ServletRequest (added this time)
  • javax.servlet.http.HttpSession (added this time)
  • org.springframework.context.ApplicationEventPublisher

epilogue

  this chapter is mainly about refreshing the application context. Next, we will continue to analyze the factory processors registered as bean s in the context, and look forward to your attention.

Added by ify on Tue, 28 Dec 2021 18:48:02 +0200