Spring源码 19 IOC getBean方法
前面实现了
ClassPathXmlApplicationContext的构造,接下来分析其调用的getBean方法。
以getBean(UserDao.class)为例。
1 AbstractApplicationContext
public <T> T getBean(Class<T> requiredType) throws BeansException {
// 断言 Bean 工厂活动
assertBeanFactoryActive();
// 获取 Bean 工厂
// 获取 Bean
return getBeanFactory().getBean(requiredType);
}
1-1 断言 Bean 工厂活动
assertBeanFactoryActive()
protected void assertBeanFactoryActive() {
if (!this.active.get()) {
if (this.closed.get()) {
// 获取显示名称
throw new IllegalStateException(getDisplayName() + " has been closed already");
}
else {
// 获取显示名称
throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
}
}
}
获取显示名称前面已经分析过了,这里不再分析。
1-1 获取 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-1 获取 Bean
getBean(requiredType)
3 DefaultListableBeanFactory
public <T> T getBean(Class<T> requiredType) throws BeansException {
// 获取 Bean
return getBean(requiredType, (Object[]) null);
}
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
// 解析 Bean
Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return (T) resolved;
}
3-1 解析 Bean
resolveBean(ResolvableType.forRawClass(requiredType), args, false)
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
// 解析 Bean 命名
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
// 获取父级 Bean 工厂
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
// 解析 Bean,递归调用
return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
}
else if (parent != null) {
ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
if (args != null) {
return parentProvider.getObject(args);
}
else {
return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
}
}
return null;
}
3-2 解析 Bean 命名
resolveNamedBean(requiredType, args, nonUniqueAsNull)
private <T> NamedBeanHolder<T> resolveNamedBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
// 获取类型的 Bean 名称
String[] candidateNames = getBeanNamesForType(requiredType);
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
for (String beanName : candidateNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = StringUtils.toStringArray(autowireCandidates);
}
}
if (candidateNames.length == 1) {
// 解析 Bean 命名
return resolveNamedBean(candidateNames[0], requiredType, args);
} else if (candidateNames.length > 1) {
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
for (String beanName : candidateNames) {
if (containsSingleton(beanName) && args == null) {
Object beanInstance = getBean(beanName);
candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
} else {
candidates.put(beanName, getType(beanName));
}
}
// 确定主要候选
String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
if (candidateName == null) {
// 确定最高优先级候选
candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
}
if (candidateName != null) {
Object beanInstance = candidates.get(candidateName);
if (beanInstance == null) {
return null;
}
if (beanInstance instanceof Class) {
// 解析 Bean 命名
return resolveNamedBean(candidateName, requiredType, args);
}
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
}
if (!nonUniqueAsNull) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
}
return null;
}
3-3 确定主要候选
determinePrimaryCandidate(candidates, requiredType.toClass())
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(), "more than one 'primary' bean found among candidates: " + candidates.keySet());
} else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
} else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
3-3 确定最高优先级候选
determineHighestPriorityCandidate(candidates, requiredType.toClass())
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (beanInstance != null) {
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(), "Multiple beans found with the same priority ('" + highestPriority + "') among candidates: " + candidates.keySet());
} else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
} else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
}
return highestPriorityBeanName;
}
参考
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源码 19 IOC getBean方法的更多相关文章
- Spring源码 19 IOC getBean
参考源 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源码 17 IOC refresh方法12
参考源 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源码 18 IOC refresh方法13
参考源 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源码 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 ...
随机推荐
- pip相关知识
正常安装语法 # 安装单个 pip install some-package # 安装指定版本 pip install some-package==版本号 # 查看当前模块版本号 pip instal ...
- 如何在矩池云上运行 AI 图像编辑工具 DragGAN
5 月,DragGAN 横空出世,在开源代码尚未公布前,就在Github上斩获近 20000 Star,彼时,页面上只有效果图和一句"Code will be released in Jun ...
- 从全球顶级数据库大会 SIGMOD 看数据库发展趋势
本文来自 NebulaGraph 的软件工程师文豪在美国费城参加 2022 年 SIGMOD 大会时的见闻.SIGMOD 是数据库领域的顶级会议之一,是 CCF 数据库 / 数据挖掘 / 内容检索领域 ...
- UI自动化测试中图片验证码的处理?
首先定位验证码image的元素,然后通过element.screenshot('a.png')截图保存到本地,通过第三方接口识别本地图片验证码
- Jmeter 如何连接mysql数据库?
1 首先安装jmeter jdbc 插件 JDBC驱动包下载教程:https://blog.csdn.net/qq_50896685/article/details/129154801 2 安装好后将 ...
- Obsidian 设置快捷键 Ctrl+Shift+J 打开OB(未启动则启动,启动未激活则激活,已激活则最小化)- autoHotKey
Obsidian 设置快捷键 Ctrl+Shift+J 打开OB(未启动则启动,启动未激活则激活,已激活则最小化)- autoHotKey 需求 将Obsidian作为主笔记软件使用,设置个快捷键,配 ...
- Spring 中不得不了解的姿势
说明 本文非原创,我只是进行了整理以及做了一些改动,仅供学习,若需进行商业使用,请联系原作者 原作者:苏三 原文链接:苏三说技术:Spring系列 Spring IOC 本章节解读的流程为Spring ...
- Windows 安装 Rust 并设置镜像加速
目录 下载rustup-init.exe(Rust安装工具) 使用镜像加速rustup安装 安装Rust 安装标准库源码 使用镜像加速cargo包下载 安装结果确认 更新.卸载和文档查看 参考文档 下 ...
- 世界银行使用.NET 7开发的免费电子问卷制作系统Survey Solution
Survey Solution (下文简称SS) 是世界银行数据部开发的一套免费电子问卷制作系统, 官网地址为: https://mysurvey.solutions/, github地址:https ...
- 使用ScottPlot库在.NET WinForms中快速实现大型数据集的交互式显示
前言 在.NET应用开发中数据集的交互式显示是一个非常常见的功能,如需要创建折线图.柱状图.饼图.散点图等不同类型的图表将数据呈现出来,帮助人们更好地理解数据.发现规律,并支持决策和沟通.本文我们将一 ...