介绍
refreshContext是springBoot启动源码中最复杂的部分了,里面的内容也非常多,将会拆分很多个章节去说。
源码
refreshContext里面就是调用AbstractApplicationContext的refresh的方法。主要的功能就是注册spring容器里面的bean,以及对bean的处理还有广播等功能。
接着看源码吧
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1 刷新context,设置占位的propertySource
prepareRefresh();
// 2 获取beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3 设置beanFactory中相应的属性
prepareBeanFactory(beanFactory);
try {
// 4 注册beanPostFactory
postProcessBeanFactory(beanFactory);
// 5
invokeBeanFactoryPostProcessors(beanFactory);
// 6
registerBeanPostProcessors(beanFactory);
// 7
initMessageSource();
// 8
initApplicationEventMulticaster();
// 9
onRefresh();
// 10
registerListeners();
// 11
finishBeanFactoryInitialization(beanFactory);
// 12
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
先介绍下prepareRefresh方法
prepareRefresh
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
// 设置flag
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化之前占位的propertySource的值
initPropertySources();
// 验证必要的属性
getEnvironment().validateRequiredProperties();
// 初始化earlyApplicationEvents,后面注册applicationEvet
// 会加入到里面去,等multicaster初始化完成之后统一发送
this.earlyApplicationEvents = new LinkedHashSet<>();
}
prepareRefresh方式是一些准备工作,对于之前environment中初始化占位的servletContextInitParams以及servletConfigInitParams的配置。具体可以看下StandardServletEnvironment这个类,environment初始化之前说过了。
由于有些配置例如servletContextInitParams这些必须要等到ServletContext封装可用了才可以,但是environment中封装配置是一个列表,有优先级顺序。所以为了优先级更高,必须排在前面,所以会先用StubPropertySource先占用,然后这边会替换。
接下来就是验证environment配置中有没有必填的配置,如果有必填的配置,但是值为空,则抛异常。
然后就是初始化earlyApplicationEvents ,这个主要的作用就是在multicaster还没有初始化的时候,讲事件先保存起来,等multicaster初始化完成之后,会调用(10) registerListeners统一发送事件的。
到这里prepareRefresh方法就说完了。接下来再看看obtainFreshBeanFactory方法
obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
对于obtainFreshBeanFactory方法呢,主要作用就是设置BeanFactory的serializationId,返回beanFactory。对于serializationId的获取是获得application的id。对于application的id在上一章说过,是ContextIdApplicationContextInitializer初始化时获取spring.application.name配置的值,要是获取不到,就默认设置成application。
对于BeanFactory的获取,主要是GenericApplicationContext类在构造时候,会默认创建DefaultListableBeanFactory。对于BeanFactory后面获取bean时候会慢慢说的。
prepareBeanFactory
继续看prepareBeanFactory源码,这里主要就是对BeanFactory的一些配置了。先简单了解下,对于各种配置不可能一下子全部明白,先有个印象。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置classLoader
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 配置BeanPostProcessor
// ApplicationContextAwareProcessor主要是为了各种Aware使用的
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// 注册特殊的依赖,在根据类型获取bean的时候用到
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 检测ApplicationListener,并将放到Listner中
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 注册bean
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 手动注册environment Bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
prepareBeanFactory的作用就是为BeanFactory添加一些属性,以及手动注册bean。
在这里加入了classloader还有Bean转换器,以及对于各种Aware使用的BeanPostProcessor,检测为Listener的BeanPostProcessor,还有手动将environment等bean注册到容器中。
postProcessBeanFactory
这个方法是可以空方法,主要是交给子类去实现,子类去注册需要的beanPostProcessor以及bean。
比如:GenericWebApplicationContext
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
if (this.servletContext != null) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
// 注册scope到beanFactory
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
// 注册context配置到beanFactory
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
总结
这章简单介绍了refreshContext的几个步骤,主要是获取初始化的准备工作,包括替换environment的占位数据,还有设置beanFactory的serializationId,以及BeanFactory的初始化,比如添加ClassLoader,还有BeanPostProcessor,手动注册bean等。
这些都是在做一些初始化的工作。后面就会涉及到实际的调用。