参考源

https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click

https://www.bilibili.com/video/BV12Z4y197MU?spm_id_from=333.999.0.0

《Spring源码深度解析(第2版)》

版本

本文章基于 Spring 5.3.15


Spring IOC 的核心是 AbstractApplicationContextrefresh 方法。

其中一共有 13 个主要方法,这里分析第 12 个:finishRefresh

1 AbstractApplicationContext

1-1 完成刷新过程

finishRefresh()
protected void finishRefresh() {
// 清除资源缓存
clearResourceCaches();
// 初始化生命周期处理器
initLifecycleProcessor();
// 获取生命周期处理器
// 刷新生命周期处理器
getLifecycleProcessor().onRefresh();
// 发布事件
publishEvent(new ContextRefreshedEvent(this));
if (!NativeDetector.inNativeImage()) {
LiveBeansView.registerApplicationContext(this);
}
}

1-2 清除资源缓存

clearResourceCaches()

2 DefaultResourceLoader

private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);

public void clearResourceCaches() {
this.resourceCaches.clear();
}

1 AbstractApplicationContext

1-2 初始化生命周期处理器

initLifecycleProcessor()
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
} else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " + "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}

1-2 获取生命周期处理器

getLifecycleProcessor()
private ResourcePatternResolver resourcePatternResolver;

LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
if (this.lifecycleProcessor == null) {
throw new IllegalStateException("LifecycleProcessor not initialized - " + "call 'refresh' before invoking lifecycle methods via the context: " + this);
}
return this.lifecycleProcessor;
}

if (this.lifecycleProcessor == null) 由于 this.lifecycleProcessor 在前面已经定义,这里直接返回。

1-2 刷新生命周期处理器

onRefresh()

3 DefaultLifecycleProcessor

public void onRefresh() {
// 启动 Beans
startBeans(true);
this.running = true;
}

3-1 启动 Beans

startBeans(true)
private void startBeans(boolean autoStartupOnly) {
// 获取 Bean 生命周期
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new TreeMap<>(); lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
phases.computeIfAbsent(
phase,
p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
).add(beanName, bean);
}
});
if (!phases.isEmpty()) {
phases.values().forEach(LifecycleGroup::start);
}
}

3-2 获取 Bean 生命周期

getLifecycleBeans()
protected Map<String, Lifecycle> getLifecycleBeans() {
// 获取 Bean 工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
Map<String, Lifecycle> beans = new LinkedHashMap<>();
String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
for (String beanName : beanNames) {
String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
if ((beanFactory.containsSingleton(beanNameToRegister) && (!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) || matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
Object bean = beanFactory.getBean(beanNameToCheck);
if (bean != this && bean instanceof Lifecycle) {
beans.put(beanNameToRegister, (Lifecycle) bean);
}
}
}
return beans;
}

1 AbstractApplicationContext

1-2 发布事件

publishEvent(new ContextRefreshedEvent(this))
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
// 获取应用程序事件多播器
// 多播事件
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}

Spring源码 17 IOC refresh方法12的更多相关文章

  1. Spring源码 18 IOC refresh方法13

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  2. Spring源码 16 IOC refresh方法11

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  3. Spring源码 15 IOC refresh方法10

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  4. Spring源码 11 IOC refresh方法6

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  5. Spring源码 07 IOC refresh方法2

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  6. Spring源码 06 IOC refresh方法1

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  7. Spring源码 14 IOC refresh方法9

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  8. Spring源码 09 IOC refresh方法4

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  9. Spring源码 08 IOC refresh方法3

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

随机推荐

  1. 【原创】史上最简单易懂的kali修改主机名方法

    前言 主机名:在一个局域网中,每台机器都有IP地址,但是IP地址不便于人们记忆.于是采用主机名,即利于主机之间的区分,又方便人们的记忆主机.--和域名差不多. 一,查看当前的主机名 ┌──(root㉿ ...

  2. STM32时钟系统配置程序源码深入分析

    一.分析程序的目的 最近我在移植实时系统是遇到了一些问题,所以决定深入了解系统时钟的配置过程,当然想要学好stm32的小伙伴也有必要学习好时钟系统的配置,所以我将学习的过程再次记录,有写得不好的地方, ...

  3. pycharm编辑器下载与安装

    pycharm编辑器下载与安装 首先是下载地址:https://www.jetbrains.com/pycharm/download/#section=windows   首先根据自己的电脑选择系统, ...

  4. 开发工具-在线计算MD5

    更新记录: 2022年6月8日 更新标题. 2022年6月1日 开始. 都记在这以后就不用到处找了. 在线计算MD5 https://www.sojson.com/md5/ http://www.ip ...

  5. JavasScript打印年月日时间代码

    就是Date的API,直接上代码啦. //打印中文的日期 function printChineseDateTime() { var now=new Date(); var str = now.get ...

  6. 物联网?快来看 Arduino 上云啦

    作者:HelloGitHub-Anthony 这里是 HelloGitHub 推出的讲解开源硬件开发平台 Arduino 的系列教程. 第一篇:Arduino 介绍和开发环境搭建 第二篇:制作温湿度显 ...

  7. 使用 Abp.Zero 搭建第三方登录模块(一):原理篇

    ​第三方登录是基于用户在第三方平台上(如微信,QQ, 百度)已有的账号来快速完成系统的登录.注册-登录等功能. 微信的鉴权 以微信的鉴权为例: 假如你的网站有一个扫码登录的功能,会弹出一个由微信提供的 ...

  8. NC21874 好串

    NC21874 好串 题目 题目描述 牛牛喜欢跟字符串玩耍,他刚刚学会了一个新操作,将一个字符串x插入另一个字符串y中(包括放在开头和结尾) 牛牛认为如果一个串是好的当这个串能按照如下方法被构造出来: ...

  9. 活动报名 | 如何基于开源项目 Tapdata PDK,快速完成数据源和目标的开发?

      近日,Tapdata 启动 PDK 插件生态共建计划,宣布开源插件开发框架 Tapdata PDK,将自身的数据接口能力开放出来,帮助开发者根据实际需求,自助接入数据源和目标,快速开启「Data ...

  10. 【Codeforces1706A】 Another String Minimization Problem

    官方标签 贪心.字符串 题目描述 输入 输出 样例输入 6 4 5 1 1 3 1 1 5 2 4 1 1 1 1 1 2 4 1 3 2 7 7 5 4 5 5 5 3 5 样例输出 ABABA B ...