本文章基于 Spring 5.3.15

Spring IOC 的核心是 AbstractApplicationContextrefresh 方法。

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

1 AbstractApplicationContext

1-1 初始化 message 源

initMessageSource()
protected void initMessageSource() {
// 获取 Bean 工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
// 如果在配置中已经配置了 messageSource,那么将 messageSource 提取并记录在 this.messageSource 中
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
} else {
// 如果用户并没有定义配置文件,那么使用临时的 DelegatingMessageSource 以便于作为调用 getMessage 方法的返回
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
// 注册单例
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}

1-2 获取 Bean 工厂

getBeanFactory()

2 AbstractRefreshableApplicationContext

public final ConfigurableListableBeanFactory getBeanFactory() {
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " + "call 'refresh' before accessing beans via the ApplicationContext");
}
return beanFactory;
}

if (beanFactory == null) 由于 beanFactory 已经被赋值,直接返回。

1 AbstractApplicationContext

1-2 注册单例

registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)

3 DefaultListableBeanFactory

public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
// 调用父类方法
super.registerSingleton(beanName, singletonObject);
// 手动更新单例名称
updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
// 按类型清除缓存
clearByTypeCache();
}

3-1 调用父类方法

super.registerSingleton(beanName, singletonObject)

4 DefaultSingletonBeanRegistry

public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
// 添加单例
addSingleton(beanName, singletonObject);
}
}

4-1 添加单例

addSingleton(beanName, singletonObject)
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

3 DefaultListableBeanFactory

3-1 手动更新单例名称

updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName))
private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) {
// 如果已开始创建 Bean
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
if (condition.test(this.manualSingletonNames)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
action.accept(updatedSingletons);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
if (condition.test(this.manualSingletonNames)) {
action.accept(this.manualSingletonNames);
}
}
}

3-2 判断是否已开始创建 Bean

private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

protected boolean hasBeanCreationStarted() {
return !this.alreadyCreated.isEmpty();
}

3-1 按类型清除缓存

clearByTypeCache()
private void clearByTypeCache() {
this.allBeanNamesByType.clear();
this.singletonBeanNamesByType.clear();
}

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

  1. Spring源码 17 IOC refresh方法12

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

  2. Spring源码 18 IOC refresh方法13

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

  3. Spring源码 16 IOC refresh方法11

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

  4. Spring源码 15 IOC refresh方法10

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

  5. Spring源码 11 IOC refresh方法6

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

  6. Spring源码 07 IOC refresh方法2

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

  7. Spring源码 06 IOC refresh方法1

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

  8. Spring源码 14 IOC refresh方法9

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

  9. Spring源码 09 IOC refresh方法4

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

随机推荐

  1. 「POI2012」井 Well

    description 你要挖井,\(n\)个地面的高度可视为\(h_i\),每次操作你可以将一个\(h_i-1\),你最多可执行\(m\)次操作. 你要任选其中一个\(h_i\)挖到\(0\),问你 ...

  2. 中国程序员容易发错音的单词「GitHub 热点速览 v.22.23」

    中国程序员容易发错音的单词,像极了学生时代的纠错本,收录着偶尔会忘记的单词.不过,它似乎更新频率跟不上我们的进步速度,至少一半以上的单词读起来是没有压力的.同样没有压力的还有让应用程序动起来的 aut ...

  3. MASA Auth - 从用户的角度看整体设计

    用户 在系统里,用户是一个核心概念.它代表了一个人的唯一身份标识,除了与角色.团队.组织架构等有关,甚至还会影响到在同一个界面不同的用户操作流程与显示内容都会发生变化,再复杂一点的话,或许在同一个系统 ...

  4. python实现对简单的运算型验证码的识别【不使用OpenCV】

    最近在写我们学校的教务系统的手机版,在前端用户执行绑定操作后,服务器将执行登录,但在登录过程中,教务系统中有个运算型的验证码,大致是这个样子的: 下面我们开始实现这个验证码的识别. 1.图片读取 从网 ...

  5. ESP8266 系统环境搭建

    1. 前言 因为ESP8266/ESP32这个开发环境没少折腾,是真没见过这么难搞又不清晰的环境. 简单开发可以使用Arduino IDE ,这个平台还是挺好的.开发使用Arduino的函数库,很高效 ...

  6. 开发工具-SSMS官方下载地址

    更新记录 2022年6月10日 完善标题. SQL Server Management Studio官方下载地址 https://docs.microsoft.com/en-us/sql/ssms/d ...

  7. .NET 处理[未能为 SSLTLS 安全通道建立信任关系]问题

    更新记录 2022年4月16日本文迁移自Panda666原博客,原发布时间:2021年7月16日. 在.NET的开发过程中,发现[基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系]问题 ...

  8. JS:构造函数

    定义:在JavaScript中,用new关键字来调用的函数,称为构造函数,构造函数首字母一般大写. 理解: 构造函数就是初始化一个实例对象,对象的prototype属性是继承一个实例对象. 创建对象, ...

  9. BUUCTF-隐藏的钥匙

    隐藏的钥匙 通过16进制打开发现flag,其中告知编码为base64,解密后加上flag{}即可 flag{377cbadda1eca2f2f73d36277781f00a}

  10. 自己实现一个自定义React项目脚手架「ReactCli」

    前言 首先为什么想到自己实现一个React脚手架呢?是因为之前刚接触create-react-app时,觉得不太灵活.虽然文件目录很清晰,但是还是觉得不如VueCLI的可以自定义配置更加灵活.当然Re ...