目录
一、背景
上一篇我们解读了准备应用上下文,本篇主要解读刷新应用上下文(上),老样子还是回顾下启动的整体流程,这样就能不迷路。
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));
}
}
}
这里调用父类ServletWebServerApplicationContext的postProcessBeanFactory方法。
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的工厂处理器等,期待你的关注。