ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-12-27 15:03:17  阅读:125  来源: 互联网

标签:SpringBoot beanFactory Alian springframework bean 源码 context new 上下文


目录

一、背景

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

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的工厂处理器等,期待你的关注。

标签:SpringBoot,beanFactory,Alian,springframework,bean,源码,context,new,上下文
来源: https://blog.csdn.net/Alian_1223/article/details/121541345

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有