Spring源码 12 IOC refresh方法7
本文章基于 Spring 5.3.15
Spring IOC 的核心是
AbstractApplicationContext的refresh方法。
其中一共有 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的更多相关文章
- Spring源码 17 IOC refresh方法12
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 18 IOC refresh方法13
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 16 IOC refresh方法11
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 15 IOC refresh方法10
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 11 IOC refresh方法6
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 07 IOC refresh方法2
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 06 IOC refresh方法1
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 14 IOC refresh方法9
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- Spring源码 09 IOC refresh方法4
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
随机推荐
- 【SSM框架】Spring笔记 --- 事务详解
1.Spring的事务管理: 事务原本是数据库中的概念,在实际项目的开发中,进行事务的处理一般是在业务逻辑层, 即 Service 层.这样做是为了能够使用事务的特性来管理关联操作的业务. 在 Spr ...
- SQL中如何修改数据库名、表名、列名?
文章目录 1.SQL中如何修改数据库的名字? 2.SQL中如何修改表的名字? 3.SQL中如何修改列的名字? 4.SQL中如何修改列的数据类型?(未完成,待续) 1.SQL中如何修改数据库名? 语法 ...
- SpringBoot Restful 接口实现
目录 SpringBoot 核心注解 SpringBoot Restful 接口实现 封装响应数据 SpringBoot 核心注解 SpringBoot 基础入门 注解 说明 Component 声明 ...
- MySQL数据库5
内容概要 pyhton操作MySQL SQL注入问题 修改表SQL语句补充 视图.触发器.储存过程 事务 流程控制 函数 索引与慢查询优化 内容详情 pyhton操作MySQL python中支持操作 ...
- 【clickhouse专栏】单机版的安装与验证
<clickhouse专栏>第三节内容,先安装一个单机版的clickhouse,是后续学习多副本或者分布式集群安装的基础内容.但基本的clickhouse是不依赖于zookeeper的,只 ...
- 记一次ms17-010复现过程
最近碰到业务需要使用msf,以前了解过,后面都忘记了.这次干脆写下来,省的每次去找别人写的. 首先是使用nmap探测端口 nmap -O -sV 192.168.153.130 --script=vu ...
- 手写一个模拟的ReentrantLock
package cn.daheww.demo.juc.reentrylock; import sun.misc.Unsafe; import java.lang.reflect.Field; impo ...
- Tapdata 在线研讨会:如何快速上手 Tapdata Cloud?
偶然接触到 Tapdata Cloud,据说不仅可以实现异构数据实时同步,还永久 100% 免费,但就是不知道怎么获取.怎么用? 打开相关文档逐渐陷入迷茫,术语."黑话"随处可见, ...
- 温湿度监测系统设计:基于 STM32 的温湿度变送器的设计与实现
前言:这个是2018年上半年完成的,这里只贴出硬件设计部分,软件设计部分可以看上位机说明书. 设计总说明 随着科学技术的不断发展,高集成度.高精度.高可靠性的一体化温湿度变送器开始 得到广泛的应用.同 ...
- 模电Multisim仿真Rb变化对Q点和电压放大倍数的影响
一.目的 研究Rb变化对Q点和Au的影响. 二.方法描述 仿真电路如下所示.晶体管采用FMMT5179其参数BF=133,RB=5Ω. (1)分別测量Rb=3MΩ和3.2MΩ时得UCEQ和Au.由于信 ...