Spring IoC依赖注入的实现

2023-11-20

看了《spring技术内幕》的第二章,学习了spring的IoC容器的实现,对其做了浅显地分析。

依赖注入的时机:如果配置文件有配置lazy-init,那么依赖注入的时机发生在用户向IoC

容器索取bean的时候,即调用beanfactory的getBean()方法的时候。

DefaultListerableBeanFactory的基类AbstractBeanFactory实现了getBean()方法。

getBean()有4种重载的方式:

public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}
	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
		return doGetBean(name, requiredType, args, false);
	}

无一例外地调用了doGetBean()这个方法。

doGetBean()方法实现分析如下:

doGetBean()仍然在AbstractBeanFactory这个类中。处理流程如下:

1.      先从缓存中去取,处理已经被创建过的单例模式的bean

Object sharedInstance = getSingleton(beanName);

2.      创建bean。

如果为singleTon

if (mbd.isSingleton()) {
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					public Object getObject() throws BeansException {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					}
				});
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}

如果为Prototype

if (mbd.isPrototype()) {
				// It's a prototype -> create a new instance.
				Object prototypeInstance = null;
				try {
					beforePrototypeCreation(beanName);
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					afterPrototypeCreation(beanName);
				}
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}

doGetBean()方法实际上调用了createBean()这个方法来创建bean。

CreateBean()方法在AbstractAutowireCapableBeanFactory这个类中实现:

Object beanInstance = doCreateBean(beanName, mbd, args);
doCreateBean()这个方法如下
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args){
BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
……

createBeanInstance()的实现:

createBeanInstance()这个方法仍然写在AbstractAutowireCapableBeanFactory这个类中,调用了instantiateBean()这个方法来创建bean

instantiateBean()这个方法实现如下

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
					public Object run() {
						return getInstantiationStrategy().instantiate(mbd, beanName, parent);
					}
				}, getAccessControlContext());
			}
			else {
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}


注意

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

使用策略来进行初始化,getInstantiationStrategy()

protected InstantiationStrategy getInstantiationStrategy() {
		return this.instantiationStrategy;
	}

instantiationStrategy在初始化的时候就写好了,

private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

spring中默认的生成bean对象是cglib库。还又另外一种方法就是jdk中的反射功能。

Class.forName().newInstance()

使用的是cglibenhancer类来创建bean

public Object instantiate(Constructor ctor, Object[] args) {
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(this.beanDefinition.getBeanClass());
			enhancer.setCallbackFilter(new CallbackFilterImpl());
			enhancer.setCallbacks(new Callback[] {
					NoOp.INSTANCE,
					new LookupOverrideMethodInterceptor(),
					new ReplaceOverrideMethodInterceptor()
			});

			return (ctor == null) ? 
					enhancer.create() : 
					enhancer.create(ctor.getParameterTypes(), args);
		}

整个调用图用下图来分析即可




做个标记

http://h-eaven.iteye.com/blog/1161979

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring IoC依赖注入的实现 的相关文章

随机推荐

  • AIGC潮水中,重新理解低代码

    如果将一句话生成应用形容成L4级的 无人驾驶 伙伴云的 AI搭建 则更像L2 级的 辅助驾驶 作者 斗斗 出品 产业家 2023年 AIGC下的低代码赛道 暗流涌动 对于 AI搭建 的搭建效果 尤其是在场景覆盖的广度上 连我自己也感觉比较意
  • Qt Creator创建C++(Day1)

    利用Qt Creator创建纯C 项目流程 1 如下图所示 按照序号选择即可 2 更改名字和选择保存路径 3 点击 下一步 4 直接点击 完成 注意事项 如果在控制台输出中文乱码修改过程如下 1 选中 工具 选项 2 将 UTF 8 改为
  • 语音活性检测器 webrtcvad

    目录 概述 安装 使用脚本 1 测试静音片段 2 清理静音片段 概述 WebRTC是一个免费 开放的框架 项目 使web浏览器通过简单的JavaScript api接口实现实时通信功能 WebRTC An open framework fo
  • 动态规划之多重背包模型

    前置知识 01背包问题 动态规划之01背包模型 如何何何的博客 CSDN博客 完全背包问题 动态规划之完全背包模型 如何何何的博客 CSDN博客 多重背包问题 给定一个有一定容量的背包 和 n 个物品 每个物品有 si 件 每个物品有其对应
  • taoCMS v3.0.2 任意文件上传漏洞(CVE-2022-23880)

    靶标介绍 taoCMS v3 0 2 文件管理处存在任意文件上传漏洞 攻击者可执行任意代码 漏洞复现 1 使用御剑扫描后台 或者直接输入 admin 就会跳转到登录界面 弱口令尝试 账号admin 密码tao 2 在文件管理处 新建文件为1
  • CVPR 2023

    点击下方卡片 关注 CVer 公众号 AI CV重磅干货 第一时间送达 点击进入 gt 计算机视觉和Transformer 交流群 作者 Oliiiver 源 知乎 编辑 CVer公众号 https zhuanlan zhihu com p
  • 使用TensorFlow Lite将深度学习模型部署到IOT系统

    使用TensorFlow Lite将深度学习模型部署到IOT系统 TensorFlow Lite简介 移动设备深度学习框架是部署在手机或者树莓派等小型移动设备上的深度学习框架 可以使用训练好的模型在手机等设备上完成推理任务 这一类框架的出现
  • yolov5--完全炼丹指南

    目录 前言 炼丹方法 收集数据集 划分数据集 yolov5模型训练 简单提升训练效果的措施 关于参数的说明 结语 前言 最近在做yolov5识别手势的项目 爬了很多坑 也排除了不少bug 记录一下 参考前人的经验 遇到写得好的文章我会推荐
  • 打印出1-10000之间的所有对称数(如121,1331,2442)。

    练习题 打印出1 10000之间的所有对称数 如121 1331 2442 自己写的代码 var isSym function num var str for var i 1 i lt 9 i 如果个位算 可去掉注释 str i str f
  • 干掉广告和钓鱼,这款神器绝了!

    大家好 我是良许 前几天 搜狐丢人丢大发了 自家的员工居然遭遇了钓鱼诈骗 据报道 某员工使用邮件时被意外钓鱼导致密码泄露 进而被冒充财务部盗发邮件 共有 24 名员工被骗取 4 万余元 要知道 搜狐可是国内最早的四大门户网站之一 同时也是国
  • 【9.19】正则表达式——sed、awk

    9 19 正则表达式 sed awk 9 4 9 5 sed 1 sed 匹配 2 sed打印具体行数 3 sed 替换功能 9 6 9 7 awk 1 awk 匹配 2 awk 数学运算表达式 3 两个字段比较大小 4 内置变量 OFS
  • Vue (三) 生命周期--钩子函数

    生命周期 Vue官网生命周期的描述 钩子函数 1 beforeCreate 创建Vue实例化之前所调用的函数 div h1 message h1 div
  • webpack高版本configuration.module has an unknown property ‘loaders‘

    webpack更换高版本后报错 webpack cli Invalid configuration object Webpack has been initialized using a configuration object that
  • ffmpeg已支持解码avs2.0

    https ffmpeg org pipermail ffmpeg devel 2016 November 202446 html PS 目前应该还是个提交的patch 待审核
  • 二叉搜索树(BST)的基本操作

    二叉搜索树 BST 的创建 增加 删除 查找 需要注意 BST的左子树必小于根 右子树必大于根 所以不存在值相同的结点 include
  • 计算机网络(自顶向下方法)中的PoP

    目录 前言 问题 解决 前言 在读 计算机网络 自顶向下方法 时 看到在讲网络结构的时候提到过PoP 但是其中有一句话始终不理解 不通顺 上网搜索也没发现相关解释文章 因此 在我把这个问题解决后 就写下了这篇文章 希望可以帮助到其他人 问题
  • Eclipse常用插件下载地址

    Eclipse常用插件下载地址 官方网站http www eclipse org downloads index php下载eclipse的最新版本 Eclipse 项目资源中心 http www ibm com developerwork
  • 2、Java 环境搭建

    Java 环境搭建 1 JDK 的简介 JDK Java Development Kit 是一组实现Java程序开发与运行的本地环境 在实际的项目的开发与运行过程之中 往往都会选择一些比较好用的桌面系统 Windows MacOS 进行开发
  • linux下定时器timer_create()的使用

    一 采用新线程派驻的方式 注 编译时 需加上 lrt include
  • Spring IoC依赖注入的实现

    看了 spring技术内幕 的第二章 学习了spring的IoC容器的实现 对其做了浅显地分析 依赖注入的时机 如果配置文件有配置lazy init 那么依赖注入的时机发生在用户向IoC 容器索取bean的时候 即调用beanfactory