【细读Spring Boot源码】重中之重refresh()
前言
版本:spring-boot-2.7.3 | spring-context-5.3.22
在Spring Boot启动过程中【细读Spring Boot源码】启动步骤 主流程详情7中applicationContext.refresh();
这个操作是加载或刷新容器,把所有的配置转换成响应的对象并存入容器。
下面看下他的具体执行流程
调用主流程
主流程使用了模板模式是一个模板方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 步骤记录器记录开始
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 准备刷新。详看1
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 告诉子类刷新内部 bean 工厂,得到Bean工厂。详看2
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 准备 bean 工厂以在此上下文中使用。详看3
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 在标准初始化后修改应用程序上下文的内部bean工厂。
// 所有bean定义都已加载,但尚未实例化bean。
// 这允许在某些应用程序上下文实现中注册特殊的BeanPostProcessors等。
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
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();
contextRefresh.end();
}
}
}
详情1——准备刷新prepareRefresh()
Springboot容器没有直接使用AbstractApplicationContext抽象类默认实现方法,Springboot容器是AnnotationConfigServletWebServerApplicationContext类,实现如下
protected void prepareRefresh() {
// 清除缓存,理解这里在清除之前容器的缓存。例如:nacos引导容器启动时使用的缓存
this.scanner.clearCache();
// 再调用AbstractApplicationContext抽象类默认实现
super.prepareRefresh();
}
看下AbstractApplicationContext抽象类默认实现。
protected void prepareRefresh() {
// Switch to active.
// 切换到活跃
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());
}
}
// Initialize any placeholder property sources in the context environment.
// 初始化上下文环境中的任何占位符属性源
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 验证标记为必需的所有属性都是可解析的
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
// 存储预刷新 ApplicationListeners
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
// 清空
this.applicationListeners.clear();
// 把早期使用的监听器存入监听器列表
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
// 允许早期应用程序事件的集合,一旦multicaster可用就发布
this.earlyApplicationEvents = new LinkedHashSet<>();
}
详看2——obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新Bean工厂
refreshBeanFactory();
// 得到Bean工厂
return getBeanFactory();
}
其中refreshBeanFactory()
是AbstractApplicationContext抽象类的一个抽象方法。
子类必须实现此方法才能执行实际的配置负载。在任何其他初始化工作之前,该方法都会通过refresh() 调用。
子类将创建一个新的bean工厂并持有对它的引用,或者返回它持有的单个BeanFactory实例。在后一种情况下,如果多次刷新上下文,通常会抛出IllegalStateException。
实际上就是:刷新内部 bean 工厂,把当前上下文的Bean工厂切换为当前的Bean工厂。
protected final void refreshBeanFactory() throws IllegalStateException {
// 如果当前值 = 期望值,则原子地将值设置为给定的更新值
// 这个来判断当前容器是否刷新过。即refreshed的值为false,就把值替换为true,并返回true。取反
if (!this.refreshed.compareAndSet(false, true)) {
// 如果刷新过就抛出异常
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
// 替换。为序列化目的指定一个id,如果需要的话,允许这个BeanFactory从这个id反序列化回BeanFactory对象。
this.beanFactory.setSerializationId(getId());
}
详看3——prepareBeanFactory(beanFactory)
配置这个工厂的标准上下文特征,例如上下文的类加载器和后处理器。
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
这个方法:添加一个新的BeanPostProcessor,该处理器将应用于该工厂创建的bean。在工厂配置期间调用。
注意: 此处提交的后处理器将按注册顺序应用; 通过实现org.springframework.core.Ordered接口表达的任何排序语义将被忽略。
请注意,自动检测的后处理器 (例如,在ApplicationContext中作为bean) 将始终在以编程方式注册的处理器之后应用。
void ignoreDependencyInterface(Class<?> ifc);
这个方法:忽略给定的依赖接口进行自动查询。
这通常将由应用程序上下文用于注册依赖关系,这些依赖关系以其他方式解决,例如通过BeanFactoryAware的BeanFactory或通过ApplicationContext的ApplicationContext。
默认情况下,仅忽略BeanFactoryAware接口。对于要忽略的其他类型,请为每种类型调用此方法。
void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue);
这个方法:用相应的autowired值注册一个特殊的依赖类型。这适用于factorycontext引用,这些引用应该是自动的,但在工厂中未定义为bean: 例如,ApplicationContext类型的依赖关系解析为bean所在的ApplicationContext实例。
注意: 在普通BeanFactory中没有注册这样的默认类型,甚至对于BeanFactory接口本身也没有。
Spring源码笔记之beanFactory.registerResolvableDependency()方法,这个文章里解释的很清楚,还有使用示例。
void registerSingleton(String beanName, Object singletonObject);
这个方法:在给定的bean名称下,在bean注册表中将给定的现有对象注册为singleton。
给定的实例应该是完全初始化的; 注册表不会执行任何初始化回调 (特别是,它不会调用InitializingBean的afterPropertiesSet方法)。给定的实例也不会收到任何破坏回调 (如dispoablebean的destroy方法)。
在full BeanFactory中运行时: 如果您的bean应该接收初始化和/或销毁回调,请注册bean定义而不是现有实例。
通常在注册表配置期间调用,但也可以用于单例的运行时注册。因此,注册表实现应该同步单例访问; 如果它支持BeanFactory的单例延迟初始化,则无论如何都必须这样做
根据上面的铺垫,看下面就很顺畅。分为3部分
- 表达式解析器
- 添加应用上下文Aware的BeanPostProcessor
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 将内部bean工厂使用上下文的类加载器等
beanFactory.setBeanClassLoader(getClassLoader());
// 忽略表达式
if (!shouldIgnoreSpel) {
// 设置Bean表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
// 添加属性编辑器注册器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 添加上下文感知处理器
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);
// 忽略应用启动步骤感知
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 其他类想要用BeanFactory.class,就注入beanFactory。下面几个同理
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && 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()));
}
// Register default environment beans.
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());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}