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.