• 前言
  • registerBeanPostProcessors
  • initMessageSource
    • 如何实际应用国际化处理
  • initApplicationEventMulticaster
  • onRefresh
  • registerListeners
  • finishBeanFactoryInitialization
    • ConversionService 转换服务
      • 接口介绍
      • 配置 ConversionService
    • ValueResolver 值处理器
    • 织入、冻结
  • finishRefresh
  • resetCommonCaches
  • 总结

前言

Spring 核心方法 refresh 刷新流程简要概述及相关源码剖析(一)
继上章分析的继续补充 Refresh 中未分析完的其他方法

registerBeanPostProcessors

在 Spring 中, AbstractApplicationContext#registerBeanPostProcessors 方法被调用时,会把所有匹配的 BPP 实现类进行实例化并且加载到容器中,以便后面进行 Bean 初始化时进行一一调用

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// 找到所有实现了 BeanPostProcessor 接口的类String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// Register BeanPostProcessorChecker that logs an info message when// a bean is created during BeanPostProcessor instantiation, i.e. when// a bean is not eligible for getting processed by all BeanPostProcessors.// 记录下 BeanPostProcessor 目标数// 此处 +1 是因为此方法的后面会添加一个 BeanPostProcessorChecker 类int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;// 添加 BeanPostProcessorChecker(主要用于记录信息)到 beanFactory 中beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// 定义存放实现了 PriorityOrdered 接口 BeanPostProcessor 集合List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();// 定义存放 spring 内部的 BeanPostProcessorList<BeanPostProcessor> internalPostProcessors = new ArrayList<>();// 定义存放实现了 Ordered 接口的 BeanPostProcessor  name 集合List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();// 定义存放普通的 BeanPostProcessor  name 集合List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();// 遍历beanFactory中存在的BeanPostProcessor的集合postProcessorNames,for (String ppName : postProcessorNames) {BeanPostProcessor bpp = null;// 如果ppName对应的BeanPostProcessor实例实现了PriorityOrdered接口,则获取到ppName对应的BeanPostProcessor的实例添加到priorityOrderedPostProcessors中if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {bpp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(bpp);}// 如果ppName对应的BeanPostProcessor实例没有实现PriorityOrdered接口,但是实现了Ordered接口,那么将ppName对应的bean实例添加到orderedPostProcessorNames中else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// orderedPostProcessorNames.add(ppName);bpp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(bpp);} else {// 否则将ppName添加到nonOrderedPostProcessorNames中// nonOrderedPostProcessorNames.add(ppName);bpp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(bpp);}// 如果ppName对应的BeanPostProcessor实例也实现了MergedBeanDefinitionPostProcessor接口,那么则将ppName对应的bean实例添加到internalPostProcessors中if (bpp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(bpp);}}// First, register the BeanPostProcessors that implement PriorityOrdered.// 首先,对实现了PriorityOrdered接口的BeanPostProcessor实例进行排序操作sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 注册实现了PriorityOrdered接口的BeanPostProcessor实例添加到beanFactory中registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// Next, register the BeanPostProcessors that implement Ordered.// 注册所有实现Ordered的beanPostProcessor// List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());/*for (String ppName : orderedPostProcessorNames) {// 根据ppName找到对应的BeanPostProcessor实例对象BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);// 将实现了Ordered接口的BeanPostProcessor添加到orderedPostProcessors集合中orderedPostProcessors.add(pp);// 如果ppName对应的BeanPostProcessor实例也实现了MergedBeanDefinitionPostProcessor接口,那么则将ppName对应的bean实例添加到internalPostProcessors中if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}*/// 对实现了Ordered接口的BeanPostProcessor进行排序操作sortPostProcessors(orderedPostProcessors, beanFactory);//  注册实现了Ordered接口的BeanPostProcessor实例添加到beanFactory中registerBeanPostProcessors(beanFactory, orderedPostProcessors);// Now, register all regular BeanPostProcessors.// 创建存放没有实现PriorityOrdered和Ordered接口的BeanPostProcessor的集合// List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());// 遍历集合/*for (String ppName : nonOrderedPostProcessorNames) {// 根据ppName找到对应的BeanPostProcessor实例对象BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);// 将没有实现PriorityOrdered和Ordered接口的BeanPostProcessor添加到nonOrderedPostProcessors集合中nonOrderedPostProcessors.add(pp);// 如果ppName对应的BeanPostProcessor实例也实现了MergedBeanDefinitionPostProcessor接口,那么则将ppName对应的bean实例添加到internalPostProcessors中if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}*///  注册没有实现PriorityOrdered和Ordered的BeanPostProcessor实例添加到beanFactory中registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// Finally, re-register all internal BeanPostProcessors.// 将所有实现了MergedBeanDefinitionPostProcessor类型的BeanPostProcessor进行排序操作sortPostProcessors(internalPostProcessors, beanFactory);// 注册所有实现了MergedBeanDefinitionPostProcessor类型的BeanPostProcessor到beanFactory中registerBeanPostProcessors(beanFactory, internalPostProcessors);// Re-register post-processor for detecting inner beans as ApplicationListeners,// moving it to the end of the processor chain (for picking up proxies etc).// 注册ApplicationListenerDetector到beanFactory中beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

对以上方法流程使用图结构和文案进行详细阅览

  1. beanFactory#getBeanNamesForType(BeanPostProcessor.class:通过 BPP 类型从 beanDefinitionNames 中找到其实现类,返回 String[] 类名数
  2. 记录 BPP 目标数量,此处 +1 原因是因为在此方法调用的后面添加了一个 BeanPostProcessorChecker 类「该类用于检测完 Bean 以后记录的日志信息」
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
  1. 创建存储实现 PriorityOrdered 接口、Ordered 接口、两者都未实现的接口【noOrdered】集合,再创建一个实现了 MergedBeanDefinitionPostProcessor 接口类型的内部集合,最后对 BPP 类数组进行遍历,判断其类型是属于哪一种,再加入到对应的集合中.
  2. 对以上四种集合进行同样的操作,按照顺序进行:PriorityOrdered —>Ordered —> noOrdered —> MergedBeanDefinitionPostProcessor

对集合中元素进行排序
向容器中注册给定的 BPP 类型的 Bean

  1. 注册 ApplicationListenerDetector 到容器中,该 BPP 在 prepareBeanFactory 中已经注册过了,再次注册只是为了后续可以直接取用

initMessageSource

上下文初始化 message 源,即不同的语言消息体,进行国际化处理,向容器中注入该 bean 实例

protected void initMessageSource() {// 获取bean工厂,一般是 DefaultListableBeanFactoryConfigurableListableBeanFactory beanFactory = getBeanFactory();// 首先判断是否已有xml文件定义了id为messageSource的bean对象if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {// 如果有,则从BeanFactory中获取这个对象this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// 当父类bean工厂不为空,并且这个bean对象是HierarchicalMessageSource类型if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {// 类型强制转换,转换为HierarchicalMessageSource的类型HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;// 判断父类的messageSource是否为空,如果等于空,则设置父类的messageSourceif (hms.getParentMessageSource() == null) {hms.setParentMessageSource(getInternalParentMessageSource());}}if (logger.isTraceEnabled()) {logger.trace("Using MessageSource [" + this.messageSource + "]");}}else {// 如果没有xml文件定义信息源对象,新建DelegatingMessageSource类作为messageSource的beanDelegatingMessageSource dms = new DelegatingMessageSource();// 给这个DelegatingMessageSource添加父类消息源dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;// 将这个messageSource实例注册到bean工厂中beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);if (logger.isTraceEnabled()) {logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");}}
}

如果程序中没有进行重定义这个 MessageSource 消息源 Bean,Spring 会默认帮我们注入一个 DelegatingMessageSource 实例

如何实际应用国际化处理

在公司中使用的国际化处理 Bean 一般是 ReloadableResourceBundleMessageSource,它可以帮我们解析 xml、properties 文件,同时可以自定义编码格式

public class LocaleConfig {@Resourceprivate PlatformConfig platformConfig;/*** 加载一下语言资源**/@Bean("messageSource")@ConditionalOnMissingBeanpublic MessageSource messageSource() {ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();// 用分号隔开各个语言资源路径String[] paths = platformConfig.getPath().split(PlatformConstants.COLON);messageSource.setBasenames(paths);messageSource.setDefaultEncoding(platformConfig.getEncoding());messageSource.setUseCodeAsDefaultMessage(true);messageSource.setFallbackToSystemLocale(false);return messageSource;}/*** 默认解析器 其中locale表示默认语言*/@Beanpublic LocaleResolver localeResolver() {return new I18nLocaleResolver();}/*** 获取请求头国际化信息*/static class I18nLocaleResolver implements LocaleResolver {@NotNull@Overridepublic Locale resolveLocale(HttpServletRequest httpServletRequest) {String languageHeader = httpServletRequest.getHeader(PlatformConstants.LANGUAGE);String languageParameter = httpServletRequest.getParameter(PlatformConstants.LANGUAGE);String language = Objects.nonNull(languageHeader) ? languageHeader : languageParameter;Locale locale = Locale.getDefault();if (!StringUtils.isEmpty(language)) {String[] split = language.split(PlatformConstants.UNDERSCORE);locale = new Locale(split[0], split[1]);}return locale;}@Overridepublic void setLocale(@NotNull HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {}}
}

配置消息源核心 Bean 以后,再配置下面的上下文国际化语言 MsgKey 内容处理,前端在 header 中传入当前的国家语言编码,后端在拦截器或者全局异常处理器调用 LocalContext#get 方法返回翻译值

public class LocalContent {private static MessageSource messageSource;public LocalContent(@Qualifier("messageSource") MessageSource messageSource) {LocalContent.messageSource = messageSource;}/*** 获取单个国际化翻译值*/public static String get(String msgKey) {return messageSource.getMessage(msgKey, null, LocaleContextHolder.getLocale());}
}

initApplicationEventMulticaster

初始化事件监听多路广播器

protected void initApplicationEventMulticaster() {// 获取当前bean工厂,一般是DefaultListableBeanFactoryConfigurableListableBeanFactory beanFactory = getBeanFactory();// 判断容器中是否存在 beanName 为 applicationEventMulticaster 的 bd,也就是说自定义的事件监听多路广播器,必须实现 ApplicationEventMulticaster 接口if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {// 如果有,则从 bean 工厂得到这个 bean 对象this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isTraceEnabled()) {logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else {// 如果没有,则默认采用 SimpleApplicationEventMulticasterthis.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isTraceEnabled()) {logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");}}
}

默认采用的是 SimpleApplicationEventMulticaster 多路广播器类,它的父类 AbstractApplicationEventMulticaster 的内部类专门用一个集合来存储所有的监听器

// 创建监听器助手类,用于存放应用程序的监听器集合,参数是否是预过滤监听器为 false
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
private class ListenerRetriever {// ApplicationListener 对象集合public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();// BeanFactory 中的 applicationListener 类型 Bean 集合// 在设置监听器时会通过 beanName 去获取监听器,再放入 applicationListeners 集合中public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
.......
}

onRefresh

该方法留给子类去实现,没有添加任何实现,以 SpringBoot 为例
ServletWebServerApplicationContext

protected void onRefresh() {// 创建主题对象super.onRefresh();/*GenericWebApplicationContextprotected void onRefresh() {this.themeSource = UiApplicationContextUtils.initThemeSource(this);}*/try {// 开始创建 web 服务->tomcatcreateWebServer();} catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);}
}

registerListeners

在所有注册的 Bean 中查找监听器,同时将监听器注册到消息广播器中,在这里就涉及到事件的发布以及事件的处理,详细内容可以阅读该文章:Spring 消息源及监听机制

protected void registerListeners() {// 遍历应用程序中存在的监听器集合,并将对应的监听器添加到监听器的多路广播器中for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// 从容器中获取所有实现了ApplicationListener接口的bd的bdName// 放入 ApplicationListenerBeans 集合中String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);// 可以直接获取监听器实例进去,无须在取用的时候再次 getBean   getApplicationEventMulticaster().addApplicationListener(this.getBean(listenerBeanName,ApplicationListener.class));}// 此处先发布早期的监听器集合Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}
}

finishBeanFactoryInitialization

实例化&初始化 Bean(非懒加载的),如果是实现了 FactoryBean 接口的话,就是懒加载的,只有当某个实例调用它的 getObject 方法才会去加载实现了 FactoryBean 接口的类实例.

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// 为上下文初始化类型转换器if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.// 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.// 尽早初始化 loadTimeWeaverAware bean,以便尽早注册它们的转换器String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.// 禁止使用临时类加载器进行类型匹配beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.// 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理beanFactory.freezeConfiguration();// 实例化剩下的单例对象beanFactory.preInstantiateSingletons();
}

ConversionService 转换服务

转换服务:从一个类型到另外一个类型的转换,提前储备一些转换器,由具体的转换器来完成对应的转换操作

接口介绍

定义类型转换器依赖于以下比较重要的接口

public interface Converter<S, T> {/*** S 类型转换成 T 类型*/@NullableT convert(S source);
}

Converter 接口:提供从源类型转换为目标类型的一个过程,具体的转换功能由其子类去实现,对于每次调用 convert(S),源对象参数保证不能为空,仅支持 1 ~ 1 类型之间的转换,例如 StringToInteger

public interface ConverterFactory<S, R> {/*** 获取转换器*/<T extends R> Converter<S, T> getConverter(Class<T> targetType);}

ConverterFactory 接口:converter 转换器的工厂类,用来获取对应的转换器【源类型转换为继承于某类的多个子类】1 ~ n 的转换,从一个目标类可转换为一个基类下的多个派生类,例如:StringToEnumConverterFactory

public interface GenericConverter {/*** 返回转换器集合可以转换源和目标类型*/@NullableSet<ConvertiblePair> getConvertibleTypes();/***  转换源对象到目标类型的描述*  源 TypeDescriptor 提供对保存正在转换的值的源字段的访问*  目标 TypeDescriptor 提供对要设置转换值的目标字段的访问*/@NullableObject convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}// 组建一个源到目的的组合
final class ConvertiblePair {private final Class<?> sourceType;private final Class<?> targetType;/*** 创建一个新的源-目标组合*/public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {Assert.notNull(sourceType, "Source type must not be null");Assert.notNull(targetType, "Target type must not be null");this.sourceType = sourceType;this.targetType = targetType;}public Class<?> getSourceType() {return this.sourceType;}public Class<?> getTargetType() {return this.targetType;}
}

GenericConverter 接口:当您需要复杂 Converter 实现时,考虑使用这个接口,支持在多个源类型和目标类型之间进行转换,例如 ArrayToCollectionConverter

public interface ConditionalConverter {/*** 判断是否匹配能够从源类型转换为目标类型*/boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}

ConditionalGenericConverter 接口:当您希望 Converter 只有在特定条件成立时才能允许,你可以希望仅在目标类上定义了特定方法才能进行转换,例如:ConditionalGenericConverter

public interface ConversionService {/*** 判断能否进行类型转换*/boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);/*** 类型转换,获取合适的转换器进行类型的转换,默认是 DefaultConversionService,也可以是自定义的*/@Nullable<T> T convert(@Nullable Object source, Class<T> targetType);@NullableObject convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
}

ConversionService:类型转换服务,用于在运行时执行类型转换的逻辑
大部分的 ConversionService 通常都实现了 ConverterRegistry【用于提供注册转换器】,ConversionService 实现委托其注册的转换器执行具体类型转换逻辑.
GenericConversionService 是 ConversionService 实现类,适用于大多数环境的通用实现

配置 ConversionService

默认值 ConversionService 可以在字符串、数字、枚举、集合、映射和其他常见类型之间进行转换,如果需要使用自定义转换器或覆盖默认转换器,需要设置 ConversionServiceFactoryBean#converters 属性,属性值可以实现任何 ConverterConverterFactoryGenericConverter接口
例如:需求,需要将一个字符串转换为一个具体的对象,如 “1_zhangsan_“ 设置为 Student 的 id 和 name 属性.

public class StudentConverter implements Converter<String,Student> {@Overridepublic Student convert(String source) {System.out.println("-----");Student s  = new Student();String[] splits = source.split("_");s.setId(Integer.parseInt(splits[0]));s.setName(splits[1]);return s;}
}
<!-- xml 方式配置 -->
<bean id="studentConverter" class="com.mashibing.selfConverter.StudentConverter"/>
<bean id ="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><property name="converters"><set><ref bean="studentConverter"/></set></property>
</bean>
// 注解方式配置
@Configuration
public class AppConfig {@Beanpublic ConversionService conversionService() {DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();conversionService.addConverter(new MyCustomConverter());return conversionService;}
}

ValueResolver 值处理器

<context:property-placeholder location="classpath:db.properties"/>

如果新增了以上标签,那么在解析以上自定义标签时,解析器 PropertyPlaceholderBeanDefinitionParser 会为我们新增对应的 org.springframework.context.support.PropertySourcesPlaceholderConfigurer 类的 BeanDefinition 进去,那么在调用 invokeBeanFactoryPostProcessors 时,同时 PropertySourcesPlaceholderConfigurer 实现了 BFPP 接口,那么就会调用 postProcessBeanFactory 方法【进行占位符变量的解析工作】,这时已经提前设置好了占位符处理器为内置的值处理器
如果没有配置以上自定义标签的话,那么 Spring 默认是不会配置的,那么在这边就会去做新增值处理器的一个操作.

织入、冻结

// 尽早初始化 loadTimeWeaverAware bean,以便尽早注册它们的转换器
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);
}// 禁止使用临时类加载器进行类型匹配
beanFactory.setTempClassLoader(null);// 冻结所有 bean 定义,说明注册 bean 定义将不被修改或任何进一步的处理
beanFactory.freezeConfiguration();// 实例化剩下的单例对象
beanFactory.preInstantiateSingletons();

LoadTimeWeaverAware 类是与 AOP 相关的
在准备实例化单例对象时即调用 preInstantiateSingletons 方法前,先把所有的 BeanDefinition 信息冻结起来,防止被修改和进一步的处理
preInstantiateSingletons 是实例化初始化 Bean 核心方法,后续单独整理一篇「Spring Bean 生命周期」文章进行详细介绍

finishRefresh

完成刷新过程,通知生命周期处理器 LifecycleProcessor 刷新过程,同时发出 ContextRefreshEvent 事件通知别人

protected void finishRefresh() {// 清除上下文级别的资源缓存(如扫描的 ASM 元数据)// 清空在资源加载器中的所有资源缓存clearResourceCaches();// 为这个上下文初始化生命周期处理器// 初始化 LifecycleProcessor:如果上下文中找到'lifecycleProcessor' 的 LifecycleProcessor Bean 对象,则使用 DefaultLifecycleProcessorinitLifecycleProcessor();// 首先将刷新传播到生命周期处理器// 上下文刷新的通知,例如自动启动的组件getLifecycleProcessor().onRefresh();// 发布最终事件// 新建 ContextRefreshedEvent 事件对象,将其发布给所有监听器publishEvent(new ContextRefreshedEvent(this));// 参与 LiveBeansView MBean,如果是活动的// LiveBeansView:Spring 用于支持JMX 服务的类// 注册当前上下文到 LiveBeansView,以支持 JMX 服务LiveBeansView.registerApplicationContext(this);
}

在 SpringBoot 启动容器时对该方法也做了特殊的处理,代码如下:

protected void finishRefresh() {//调用父类 finishRefresh 方法super.finishRefresh();// 启动 webServerWebServer webServer = startWebServer();if (webServer != null) {// 发布 webServer 初始化完成事件publishEvent(new ServletWebServerInitializedEvent(webServer, this));}
}

resetCommonCaches

重置在 Spring 核心的内置缓存,因为我们可能不再需要单例 bean 元数据

protected void resetCommonCaches() {// 清除方法、属性缓存ReflectionUtils.clearCache();AnnotationUtils.clearCache();// 清除对象映射、序列化包装对象缓存ResolvableType.clearCache();CachedIntrospectionResults.clearClassLoader(getClassLoader());
}

总结

至此,AbstractApplicationContext#refresh 方法中涉及到的 13 个方法简要已经分析完成了
编写文章不易,觉得可以帮助到你的内容,帮忙给个赞

Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)相关推荐

  1. Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(一)

    前言 Spring 启动流程解析 Refresh 内部方法全解析 prepareRefresh obtainFreshBeanFactory AbstractApplicationContext 类以 ...

  2. 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  3. 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  4. 详述 Spring MVC 启动流程及相关源码分析

    文章目录 Web 应用部署初始化过程(Web Application Deployement) Spring MVC 启动过程 Listener 的初始化过程 Filter 的初始化 Servlet ...

  5. 【Android 异步操作】AsyncTask 异步任务 ( AsyncTask 异步任务执行方法 execute 方法相关源码解析 )

    文章目录 一.AsyncTask 异步任务执行方法 execute() 引入 二.AsyncTask 异步任务执行方法 execute() 三.sDefaultExecutor 线程池解析 四.exe ...

  6. spring源码扩展点与实战(一)

    前言 我们在使用 spring 框架的时候,有时候需要做一些定制化开发,这个时候就有必要对 spring 进行一些个性化扩展.spring 的代码本身就是一门艺术,可以非常方便进行扩展,但是有时候应用 ...

  7. spring源码扩展点与实战(二)

    在上一篇文章<spring源码扩展点>,我们简单的介绍了 spring 的几个常用扩展点,了解了 BeanPostProcessor, BeanFactoryPostProcessor, ...

  8. c语言回溯实验报告,实验报告: 人脸识别方法回溯与实验分析 【OpenCV测试方法源码】...

    实验报告: 人脸识别方法回顾与实验分析 [OpenCV测试方法源码] 趁着还未工作,先把过去做的东西整理下出来~ (涉及个人隐私,源码不包含测试样本,请谅解~) 对实验结果更感兴趣的朋友请直接看第5章 ...

  9. 查看chrome插件源码(扩展程序源码)方法以及Mac如何显示资源库(Library)

    一. 查看chrome插件源码(扩展程序源码)的方法 1.1 crx 是chrome 插件源码打包后的文件后缀名: 一个应用(扩展)其实是压缩在一起的一组文件,包括HTML,CSS,Javascrip ...

最新文章

  1. 据说这是中途接手别人项目时的场景
  2. 十一. 图形、图像与多媒体1.绘图基础
  3. c语言在keil上程序合并,keil中怎么把两个c程序怎么同时同时编译生成一个hex文件...
  4. python代码画小狗_程序员教你用代码手绘一只可爱的小狗,正好拿去送给女朋友给她个惊喜...
  5. Delphi应用程序的调试(三)监视变量
  6. WINDOWS10的任务管理器不能自动刷新?
  7. 前端关于点击链接下载文件的解决办法
  8. 在线画板_在线画画_在线画图工具-速写板
  9. 华为linux用什么浏览器,Linux系统浏览器最受用户欢迎前十排名
  10. CDA level 1 业务分析师 之 业务分析部分PART 5 多维数据透视分析(10%)
  11. linux 密码输入回显星号
  12. Android Exif 解析
  13. 金彩教育:如何提升店铺的信誉
  14. jQuery 官网下载js
  15. 知识产权行业获客难?一招解决
  16. Remember-Me功能
  17. 如何使用ROS控制真实UR5机器人
  18. allegro的正片和负片概念
  19. 奥里给,干了兄弟们。
  20. 51单片机led点阵C语言,51单片机驱动LED点阵扫描显示C语言程序

热门文章

  1. 计算机竞赛主持人开场白台词,六一主持词开场白台词.doc
  2. ULN2003步进电机 5V/12V步进电机 28BYJ-48步进电机 13003驱动板开发者文档
  3. 希沃白板5是最好的白板软件吗
  4. 左旋转、右旋转、双旋
  5. python画k线图_python画k线图
  6. python+OpenCV 图片合成视频
  7. 瑞芯微RK3308方案简介
  8. 福建瑞芯微电子实习第一天
  9. 产品经理的必备知识点
  10. Unity_URP管线下粒子发射多个模型叠加在一起,会有破面的解决方法