目录

  • 一、背景
    • 1.1、run方法整体流程
    • 1.2、刷新的整体调用流程
    • 1.3、本文解读范围
  • 二、准备刷新
    • 2.1、准备刷新的流程
    • 2.2、初始化上下文环境中servlet相关属性源
    • 2.3、校验require属性
    • 2.4、预刷新应用程序监听器
  • 三、通知子类刷新内部beanFactory
  • 四、准备beanFactory
    • 4.1、准备beanFactory的整体流程
    • 4.2、StandardBeanExpressionResolver
    • 4.3、其他简单说明
  • 五、上下文中子类对bean工厂进行后处理
  • 结语

一、背景

  上一篇我们解读了准备应用上下文,本篇主要解读刷新应用上下文(上),老样子还是回顾下启动的整体流程,这样就能不迷路。

1.1、run方法整体流程

  接下来的几个方法所在类的具体路径: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、创建并启动计时监控类StopWatch stopWatch = new StopWatch();stopWatch.start();// 2、初始化启动上下文、初始化应用上下文DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;// 3、设置无头属性:“java.awt.headless”,默认值为:true(没有图形化界面)configureHeadlessProperty();// 4、创建所有 Spring 运行监听器并发布应用启动事件SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {// 5、初始化默认应用参数类ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 6、根据运行监听器和应用参数来准备 Spring 环境ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);configureIgnoreBeanInfo(environment);// 7、创建 Banner 并打印Banner printedBanner = printBanner(environment);// 8、创建应用上下文context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);// 9、准备应用上下文prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 10、刷新应用上下文refreshContext(context);// 11、应用上下文刷新后置处理afterRefresh(context, applicationArguments);// 12、停止计时监控类stopWatch.stop();// 13、输出日志记录执行主类名、时间信息if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}// 14、发布应用上下文启动完成事件listeners.started(context);// 15、执行所有 Runner 运行器callRunners(context, applicationArguments);} catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {// 16、发布应用上下文就绪事件listeners.running(context);} catch (Throwable ex) {// 17、错误处理handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}// 18、返回应用上下文return context;}

1.2、刷新的整体调用流程

  此方法所在类的具体路径:org.springframework.boot.SpringApplication

 private void refreshContext(ConfigurableApplicationContext context) {if (this.registerShutdownHook) {// 又增加一个监听器ApplicationContextClosedListener,上一文我们讲过准备刷新是11个,现在就是12个了shutdownHook.registerApplicationContext(context);}refresh(context);}protected void refresh(ConfigurableApplicationContext applicationContext) {// 最终实现是AbstractApplicationContext的refresh方法applicationContext.refresh();}

  此方法所在类的具体路径:org.springframework.context.support.AbstractApplicationContext

@Overridepublic void refresh() throws BeansException, IllegalStateException {// 同步的方式刷新synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// 准备此上下文以进行刷新prepareRefresh();// 告诉子类刷新内部bean工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 准备bean工厂,以便在此上下文中使用prepareBeanFactory(beanFactory);try {// 允许在上下文中子类对bean工厂进行后处理postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// 调用在上下文中注册为bean的工厂处理器invokeBeanFactoryPostProcessors(beanFactory);// 注册拦截bean创建的BeanPostProcessorregisterBeanPostProcessors(beanFactory);beanPostProcess.end();// 为此上下文初始化消息源,也就是注册DelegatingMessageSourceinitMessageSource();// 为此上下文初始化事件multicasterinitApplicationEventMulticaster();// 初始化特定上下文子类中的其他特殊bean,比如创建内置的Servlet容器onRefresh();// 检查监听器bean并注册它们registerListeners();// 实例化所有剩余的(非惰性初始化)单例finishBeanFactoryInitialization(beanFactory);// 最后一步:发布相应的事件finishRefresh();} catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);}// 销毁已创建的单例以避免悬空资源destroyBeans();// 重置“active”标志cancelRefresh(ex);// 将异常传播到调用方throw ex;} finally {//重置Spring核心中的常见内省缓存,因为我们可能不再需要单例bean的元数据了。。。resetCommonCaches();contextRefresh.end();}}}
  • 同步操作
  • 准备此上下文以进行刷新
  • 告诉子类刷新内部bean工厂
  • 准备bean工厂,以便在此上下文中使用
  • 允许在上下文中子类对bean工厂进行后处理
  • 调用在上下文中注册为bean的工厂处理器
  • 注册拦截bean创建的BeanPostProcessor
  • 为此上下文初始化消息源,也就是注册DelegatingMessageSource
  • 为此上下文初始化事件Multicaster
  • 初始化特定上下文子类中的其他特殊bean
  • 检查监听器bean并注册它们
  • 实例化所有剩余的(非惰性初始化)单例
  • 发布相应的事件

1.3、本文解读范围

  本文主要讲解refresh()方法的部分内容,也就是:

 // 准备此上下文以进行刷新prepareRefresh();// 告诉子类刷新内部bean工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 准备bean工厂,以便在此上下文中使用prepareBeanFactory(beanFactory);try {// 允许在上下文中子类对bean工厂进行后处理postProcessBeanFactory(beanFactory);// 后面省略,本到此处} catch (BeansException ex) {}finally{}

  整个方法的内容比较多,为了比较详细的解读,我们就分多个部分解读,本文就解读到上下文中子类对bean工厂进行后处理。

二、准备刷新

2.1、准备刷新的流程

  此方法所在类的具体路径:org.springframework.context.support.AbstractApplicationContext

 protected void prepareRefresh() {// 记录时间this.startupDate = System.currentTimeMillis();// 上下文关闭的标志this.closed.set(false);// 上下文切换到激活状态this.active.set(true);if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);} else {logger.debug("Refreshing " + getDisplayName());}}// 初始化上下文环境中servlet相关属性源// 通过调用子类GenericWebApplicationContext重写后的方法来实现initPropertySources();//验证标记为“required”的所有属性是否可解析://具体可以参阅ConfigurablePropertyResolver#setRequiredPropertiesgetEnvironment().validateRequiredProperties();// 存储预刷新应用程序监听器if (this.earlyApplicationListeners == null) {// 此时上下文里是12个监听器,具体可有看我上一篇文章里11个的来源及本文中的添加的1个this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);} else {// 将本地应用程序监听器重置为预刷新状态this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// 一旦multicaster 可用,允许早期的ApplicationEvents进行发布this.earlyApplicationEvents = new LinkedHashSet<>();}
  • 将上下文切换到激活状态
  • 通过调用子类GenericWebApplicationContext重写后的方法来初始化上下文环境中servlet相关属性源
  • 预刷新应用程序监听器处理
  • 定义早期ApplicationEvent事件

2.2、初始化上下文环境中servlet相关属性源

  此方法所在类的具体路径:org.springframework.web.context.support.GenericWebApplicationContext

public class GenericWebApplicationContext extends GenericApplicationContextimplements ConfigurableWebApplicationContext, ThemeSource {@Overrideprotected void initPropertySources() {// 获取环境为ApplicationServletEnvironmentConfigurableEnvironment env = getEnvironment();if (env instanceof ConfigurableWebEnvironment) {// ApplicationServletEnvironment 继承了StandardServletEnvironment// StandardServletEnvironment 实现了ConfigurableWebEnvironment((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);}}
}

  此方法所在类的具体路径:org.springframework.web.context.support.StandardServletEnvironment

public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {@Overridepublic void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {// getPropertySources()的值具体可以参考我之前的文章:启动流程分析之应用环境准备WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);}
}

大致如下结构:

 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");// servletContextInitParamsString name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;if (servletContext != null && sources.get(name) instanceof StubPropertySource) {sources.replace(name, new ServletContextPropertySource(name, servletContext));}// servletConfigInitParamsname = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {sources.replace(name, new ServletConfigPropertySource(name, servletConfig));}}
}

  servletContext为null故什么都没有做

2.3、校验require属性

public abstract class AbstractEnvironment implements ConfigurableEnvironment {private final ConfigurablePropertyResolver propertyResolver;@Overridepublic void validateRequiredProperties() throws MissingRequiredPropertiesException {// 这里的propertyResolver为PropertySourcesPropertyResolver,这个值是在prepareEnvironment方法创建环境时初始化赋值的this.propertyResolver.validateRequiredProperties();}
}

  这里的propertyResolver为PropertySourcesPropertyResolver,这个值是在prepareEnvironment方法创建环境时初始化赋值的,PropertySourcesPropertyResolver 继承抽象类 AbstractPropertyResolver

public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {}

  AbstractPropertyResolver又实现了接口ConfigurablePropertyResolver

public abstract class AbstractPropertyResolver implements ConfigurablePropertyResolver {private final Set<String> requiredProperties = new LinkedHashSet<>();@Overridepublic void validateRequiredProperties() {MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();// requiredProperties是空的for (String key : this.requiredProperties) {if (this.getProperty(key) == null) {ex.addMissingRequiredProperty(key);}}if (!ex.getMissingRequiredProperties().isEmpty()) {throw ex;}}
}

2.4、预刷新应用程序监听器

  此时的预刷新应用程序监听器applicationListeners(12个):

  • RSocketPortInfoApplicationContextInitializer的内部类Listener
  • ServerPortInfoApplicationContextInitializer
  • ConditionEvaluationReportLoggingListener的内部类ConditionEvaluationReportListener
  • EnvironmentPostProcessorApplicationListener
  • AnsiOutputApplicationListener
  • LoggingApplicationListener
  • BackgroundPreinitializer
  • DelegatingApplicationListener
  • ParentContextCloserApplicationListener
  • ClearCachesApplicationListener
  • FileEncodingApplicationListener
  • SpringApplicationShutdownHook的内部类ApplicationContextClosedListener

三、通知子类刷新内部beanFactory

  此方法所在类的具体路径:org.springframework.context.support.AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();// 返回的beanFactory为DefaultListableBeanFactory,具体可以查看我之前的文章:启动流程分析之创建应用上下文return getBeanFactory();}
}
  • 刷新beanFactory
  • 获取beanFactory,此处得到的是DefaultListableBeanFactory

  我们看下refreshBeanFactory(),此方法所在类的具体路径:org.springframework.web.context.support.GenericWebApplicationContext

public class GenericWebApplicationContext extends GenericApplicationContextimplements ConfigurableWebApplicationContext, ThemeSource {@Overrideprotected final void refreshBeanFactory() throws IllegalStateException {// 这里的refreshed是一个刷新标志,未刷新就设置为trueif (!this.refreshed.compareAndSet(false, true)) {throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");}// 获取的上下文id为application// 设置beanFactory的序列化idthis.beanFactory.setSerializationId(getId());}
}

  此方法所在类的具体路径:org.springframework.beans.factory.support.DefaultListableBeanFactory

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {// 序列化工厂映射:key为序列化id,value为弱引用对象private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =new ConcurrentHashMap<>(8);// 此工厂的可序列化Id,用于序列化@Nullableprivate String serializationId;public void setSerializationId(@Nullable String serializationId) {if (serializationId != null) {// 序列化id不为空时,把DefaultListableBeanFactory通过弱引用加入映射serializableFactories.put(serializationId, new WeakReference<>(this));} else if (this.serializationId != null) {serializableFactories.remove(this.serializationId);}// 设置应用上下文序列化id(唯一)this.serializationId = serializationId;}
}

四、准备beanFactory

4.1、准备beanFactory的整体流程

  此方法所在类的具体路径:org.springframework.context.support.AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {private static final boolean shouldIgnoreSpel = SpringProperties.getFlag("spring.spel.ignore");protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 告诉内部bean工厂使用上下文的类加载器beanFactory.setBeanClassLoader(getClassLoader());// 如果没有配置属性spring.spel.ignore,则默认为false,也就是支持spelif (!shouldIgnoreSpel) {// 实例化一个标准Bean表达式解析器StandardBeanExpressionResolverbeanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));}// 添加属性注册编辑器,ResourceEditorRegistrar的registerCustomEditors方法主要是注册简单通用常用类型的属性编辑器beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 添加后置处理器,使用上下文回调配置beanFactorybeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 添加依赖项检查和autowire时要忽略的依赖项接口。默认情况下,仅忽略BeanFactory接口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);// BeanFactory接口未在普通工厂中注册为可解析类型// MessageSource作为bean注册(并找到自动连接)beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// 注册早期的后置处理器用于检测内部bean,像ApplicationListenerbeanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// 检测LoadTimeWeaver并准备编织(如果发现)if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// 为了类型匹配设置临时类加载器beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// 注册默认环境bean// 如果beanFactory里不存在beanName为environment的bean,则注册environmentif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}// 如果beanFactory里不存在beanName为systemProperties的bean,则注册systemPropertiesif (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}// 如果beanFactory里不存在beanName为systemEnvironment的bean,则注册systemEnvironmentif (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}// 如果beanFactory里不存在beanName为applicationStartup的bean,则注册applicationStartupif (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());}}}
  • 告诉内部bean工厂使用上下文的类加载器
  • 实例化一个标准Bean表达式解析器StandardBeanExpressionResolver
  • 添加后置处理器,使用上下文回调配置beanFactory
  • 添加属性注册编辑器ResourceEditorRegistrar
  • 添加依赖项检查和autowire时要忽略的依赖项接口
  • 注册早期的后置处理器用于检测内部bean
  • 检测LoadTimeWeaver并准备编织
  • 注册默认环境bean(environment、systemProperties、systemEnvironment、applicationStartup

4.2、StandardBeanExpressionResolver

  此方法所在类的具体路径:org.springframework.context.expression.StandardBeanExpressionResolver

public class StandardBeanExpressionResolver implements BeanExpressionResolver {// 默认表达式前缀: "#{"public static final String DEFAULT_EXPRESSION_PREFIX = "#{";// 默认表达式后缀: "}"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));}
}

  构造方法就是获取了一个表达式解析器SpelExpressionParser,而SpelExpressionParser的构造方法(主要参数是SpelParserConfiguration)主要是初始化了Spel编译模式,该模式主要由三种:

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

  本文这里是默认的SpelCompilerMode.OFF,关于SpelParserConfiguration的构造方法比较简单,大家可以自行查阅。

4.3、其他简单说明

1、ResourceEditorRegistrar 的registerCustomEditors方法主要是注册简单通用常用类型的属性编辑器

2、ApplicationListenerDetector:主要作用:

  • 在Bean初始化完成之后:如果bean是 ApplicationListener的实例,并且Bean是单例,就会加入到this.applicationListeners
  • 在Bean销毁之前搞事情:如果Bean是一个ApplicationListener的实例,则会从事件广播器ApplicationEventMulticaster中删除

3、ApplicationContextAwareProcessor 可用来处理实现ApplicationContextAware的bean对象,它的postProcessBeforeInitialization方法是要忽略的依赖项接口(具体见第4点),则注入Aware接口,否则直接返回bean

4、要忽略的依赖项接口(创建应用上下文时添加了三个):

  • org.springframework.context.ApplicationEventPublisherAware(本次添加)
  • org.springframework.context.MessageSourceAware(本次添加)
  • 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

5、在普通工厂中不是可解析型的beanFactory接口

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

五、上下文中子类对bean工厂进行后处理

  此方法所在类的具体路径:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext

public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContextimplements 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));}}
}

  这里调用父类ServletWebServerApplicationContext的postProcessBeanFactory方法。

public class ServletWebServerApplicationContext extends GenericWebApplicationContextimplements ConfigurableWebServerApplicationContext {@Overrideprotected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 添加后置处理器(添加完就3个了)beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));// 添加要忽略的依赖项接口()beanFactory.ignoreDependencyInterface(ServletContextAware.class);// 注册web应用程序作用域registerWebApplicationScopes();}
}
  • 添加后置处理器
  • 添加要忽略的依赖项接口
  • 注册web应用程序作用域
public class WebApplicationContextServletContextAwareProcessor extends ServletContextAwareProcessor {private final ConfigurableWebApplicationContext webApplicationContext;public WebApplicationContextServletContextAwareProcessor(ConfigurableWebApplicationContext webApplicationContext) {Assert.notNull(webApplicationContext, "WebApplicationContext must not be null");this.webApplicationContext = webApplicationContext;}
}

后置处理器:

  • ApplicationContextAwareProcessor(prepareBeanFactory方法里添加)
  • ApplicationListenerDetector(prepareBeanFactory方法里添加)
  • WebApplicationContextServletContextAwareProcessor(本次添加)

要忽略的依赖项接口:

  • org.springframework.context.ApplicationEventPublisherAware
  • org.springframework.context.MessageSourceAware
  • org.springframework.web.context.ServletContextAware(本次添加)
  • 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

  关于ExistingWebApplicationScopes的实例化:

 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);}}}}

  关于registerWebApplicationScopes方法:

public abstract class WebApplicationContextUtils {public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {registerWebApplicationScopes(beanFactory, null);}public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,@Nullable ServletContext sc) {// 注册request作用域beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());// 注册session作用域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);}// 添加普通工厂中不是可解析型的beanFactory接口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接口(文章之前加入了4个):

  • javax.servlet.ServletResponse(本次添加)
  • org.springframework.context.ApplicationContext
  • org.springframework.web.context.request.WebRequest(本次添加)
  • org.springframework.beans.factory.BeanFactory
  • org.springframework.core.io.ResourceLoader
  • javax.servlet.ServletRequest(本次添加)
  • javax.servlet.http.HttpSession(本次添加)
  • org.springframework.context.ApplicationEventPublisher

结语

  本章节主要是讲解刷新应用上下文的一部分,接下里我们会继续分析在上下文中注册为bean的工厂处理器等,期待你的关注。

Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(上)相关推荐

  1. Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(中)

    目录 一.背景 1.1.刷新的整体调用流程 1.2.本文解读范围 二.调用后处理器 2.1.调用在上下文中注册为beanFactory的后置处理器 2.2.invokeBeanFactoryPostP ...

  2. Alian解读SpringBoot 2.6.0 源码(七):启动流程分析之准备应用上下文

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.准备应用上下文 2.1.整体流程 2.2.设置环境 2.3.应用上下文进行后置处理 2.4.应用所有初始化器 2.5.发布应用上下 ...

  3. Alian解读SpringBoot 2.6.0 源码(十):启动流程之自动装配原理

    目录 一.背景 1.1.主类的加载 1.2.后置处理器的获取 二.配置类后处理器 2.1.获取配置类 2.2. 2.3.解析主类 2.3.1.整体解析过程 2.3.2.核心解析过程 2.3.3.延迟导 ...

  4. Alian解读SpringBoot 2.6.0 源码(六):启动流程分析之创建应用上下文

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.创建应用上下文 2.1.初始化入口 2.2.初始化AbstractApplicationContext 2.3.初始化Generi ...

  5. Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(下)

    目录 一.背景 1.1.刷新的整体调用流程 1.2.本文解读范围 二.初始化特定上下文子类中的其他特殊bean 2.1.初始化主体资源 2.2.创建web服务 三.检查监听器bean并注册它们 四.实 ...

  6. Alian解读SpringBoot 2.6.0 源码(九):启动流程分析之应用上下文刷新后处理(启动完成事件,Runner运行器,就绪事件)

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.应用上下文刷新后置处理 三.时间信息.输出日志记录执行主类名 四.发布应用上下文启动完成事件 4.1.ApplicationSta ...

  7. Alian解读SpringBoot 2.6.0 源码(二):启动流程分析之监听器解析

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.记录应用启动的开始时间 三.初始化启动上下文 3.1.初始化启动上下文 3.2.初始化应用程序事件广播器 3.3.初始化应用上下文 ...

  8. Alian解读SpringBoot 2.6.0 源码(四):启动流程分析之应用环境准备

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.应用环境准备 2.1.准备环境的整体流程 2.2.创建环境 2.3.配置环境 2.3.1.注册默认的转换器.格式化组件 2.3.1 ...

  9. Alian解读SpringBoot 2.6.0 源码(一):SpringApplication对象创建(Spring工厂加载机制)

    目录 一.背景 二.SpringApplication实例化 2.1.实例化方法入口 2.2.推断应用程序类型 2.3.Spring工厂加载机制 2.3.1.获取Spring工厂实例(重要) 2.3. ...

最新文章

  1. Wireshark运算符!=无法正常工作
  2. 对比学习系列论文MoCo v1(二):Momentum Contrast for Unsupervised Visual Representation Learning
  3. autoLayout自动布局
  4. Getting Started with the Table Component
  5. Guava 是个风火轮之基础工具(4)
  6. Linux查看网卡带宽
  7. Deep learning:十六(deep networks)
  8. Facebook Graph API(2)--读取数据之picture
  9. 合肥师范学院计算机组成原理实验,计算机组成原理实验教学探索
  10. c语言程序设计教程实验指导吴国栋,C语言程序设计教程实验指导
  11. 08系统服务器多开教程,一个四开战士的多开工具 宏及经验全面教程
  12. 创世神曲java官网_创世神曲官网下载
  13. 学前端,学线下班还是丁鹿学堂或者慕课网?
  14. 淘宝轮播图片制作技巧
  15. 护眼体验新升级,引领2023护眼风潮,南卡Pro护眼台灯评测报告
  16. html列表序号为圆点的,HTML_列表标签
  17. 多版本中文停用词词表 + 多版本英文停用词词表 + python词表合并程序
  18. CSS实现进度条和订单进度条
  19. hive表信息查询:查看表结构、表操作、建表语句
  20. 小程序从申请到发布的步骤

热门文章

  1. matlab 平抛运动,MATLAB计算平抛阻尼运动
  2. Python数据结构与算法-动态规划(钢条切割问题)
  3. Android Bitmap内存限制
  4. BCGControlBar Pro MFC用户界面控件常见问题大全
  5. 2021年秋PTA乙 7-2 数以类聚 (20 分)
  6. PrimeNumber MultTable LeapYear
  7. 【笔记】机器学习所涉及到的“微积分”知识
  8. PHP:Fatal error: Class 'COM' not found in … 的解决办法
  9. Imagination B-Series GPU介绍
  10. python脚本给微信好友自动发晚安消息