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

目录

一、背景

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

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

@Override
	public 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创建的BeanPostProcessor
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// 为此上下文初始化消息源,也就是注册DelegatingMessageSource
				initMessageSource();

				// 为此上下文初始化事件multicaster
				initApplicationEventMulticaster();

				// 初始化特定上下文子类中的其他特殊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#setRequiredProperties
		getEnvironment().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 GenericApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource {
	@Override
	protected void initPropertySources() {
		// 获取环境为ApplicationServletEnvironment
		ConfigurableEnvironment 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 {
	@Override
	public 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");
		// 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为null故什么都没有做

2.3、校验require属性

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

	@Override
	public 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<>();

	@Override
	public 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 DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		// 返回的beanFactory为DefaultListableBeanFactory,具体可以查看我之前的文章:启动流程分析之创建应用上下文
		return getBeanFactory();
	}
}
  • 刷新beanFactory
  • 获取beanFactory,此处得到的是DefaultListableBeanFactory

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

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

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

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
		
	// 序列化工厂映射:key为序列化id,value为弱引用对象
	private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
			new ConcurrentHashMap<>(8);

	// 此工厂的可序列化Id,用于序列化
	@Nullable
	private 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 DefaultResourceLoader
		implements ConfigurableApplicationContext {

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

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// 告诉内部bean工厂使用上下文的类加载器
		beanFactory.setBeanClassLoader(getClassLoader());
		// 如果没有配置属性spring.spel.ignore,则默认为false,也就是支持spel
		if (!shouldIgnoreSpel) {
			// 实例化一个标准Bean表达式解析器StandardBeanExpressionResolver
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		}
		// 添加属性注册编辑器,ResourceEditorRegistrar的registerCustomEditors方法主要是注册简单通用常用类型的属性编辑器
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// 添加后置处理器,使用上下文回调配置beanFactory
		beanFactory.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,像ApplicationListener
		beanFactory.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,则注册environment
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		// 如果beanFactory里不存在beanName为systemProperties的bean,则注册systemProperties
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		// 如果beanFactory里不存在beanName为systemEnvironment的bean,则注册systemEnvironment
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		// 如果beanFactory里不存在beanName为applicationStartup的bean,则注册applicationStartup
		if (!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 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));
		}
	}
}

  这里调用父类ServletWebServerApplicationContextpostProcessBeanFactory方法。

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
		implements ConfigurableWebServerApplicationContext {
	@Override
	protected 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的工厂处理器等,期待你的关注。

上一篇:.NET Core基础篇之:白话管道中间件


下一篇:Android - NumberImageView (消息图标)