详解Spring中getBean()方法

article/2025/10/26 3:33:15

我们日常会经常使用getBean()方法从spring容器中获取我们需要的bean。那么,getBean()方法是怎么一步步完成从spring容器中获取bean的呢?

下面我们就通过源码分析一下。

一、主要代码分析

  基于:spring5.1

 入口:AbstractBeanFactory类的doGetBean():

	public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  throws BeansException {//beanName转换,这里主要有两方面的考虑://1:如果beanName是以&开头的,则表明是要返回FactoryBean本身//而不是其生产出来的对象,而FactoryBean存储的时候,跟普通的bean一样//2:如果传入的是别名,则是需要转换为实际的beanName的			final String beanName = transformedBeanName(name);Object bean;// 检查bean是否已经存在了缓存中Object sharedInstance = getSingleton(beanName);//不为空则表明之前被创建过if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {.............}//这里对于普通的bean,则会直接的返回,//如果是FactoryBean类型的则会创建对应的实例返回bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {//如果是正在创建的Prototype类型的bean,无法处理该类型循环依赖的问题,则直接抛出异常信息		if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 查看父类中是否有相关的bean的定义信息BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// 如果name是以&开头的  则返回&+beanName的格式String nameToLookup = originalBeanName(name);if (args != null) {//递归去父类中查找return (T) parentBeanFactory.getBean(nameToLookup, args);}else {//递归去父类中查找return parentBeanFactory.getBean(nameToLookup, requiredType);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {//将父类的定义的BeanDefinition与子类的BeanDefinition进行合并覆盖final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);//判断bean是否有dependsOn 类的依赖//如果没有循环依赖,则先创建所dependsOn依赖的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {//这里主要是判断是否有以下这种类型的依赖://<bean id="beanA" class="BeanA" depends-on="beanB">//<bean id="beanB" class="BeanB" depends-on="beanA">//如果有,则直接抛出异常if (isDependent(beanName, dep)) {.......}registerDependentBean(dep, beanName);getBean(dep);}}// 处理完bean的依赖关系,则开始来创建beanif (mbd.isSingleton()) {//创建单例的bean,这里的createBean下文将详细讲解sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {//创建原型的beanObject prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {//创建其他生命周期的beanString scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {.........}try {Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {........}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// bean的类型转换if (requiredType != null && 
bean != null && !requiredType.isAssignableFrom(bean.getClass())) {try {return getTypeConverter().convertIfNecessary(bean, requiredType);}catch (TypeMismatchException ex) {........}}return (T) bean;}

 二、主要方法分析

整个getBean大的流程如上所示,下面我们分析一下上面源码中几个比较重要的方法:

1、transformedBeanName()方法: 

	protected String transformedBeanName(String name) {//如果beanName是以&开头的  则截取掉开头的&return canonicalName(BeanFactoryUtils.transformedBeanName(name));}public String canonicalName(String name) {String canonicalName = name;// 循环的去获取别名,直到获取到真实的beanName//aliasA->aliasB->beanNameString resolvedName;do {resolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;}

2、getSingleton方法

	public Object getSingleton(String beanName) {return getSingleton(beanName, true);}//判断是否有缓存起来的beanprotected Object getSingleton(String beanName, boolean allowEarlyReference) {//singletonObjects保存的为实例化并赋值过的bean,可以直接使用Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {//earlySingletonObjects主要是保存允许提前暴露出来的bean//主要是为了解决循环依赖的问题singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return (singletonObject != NULL_OBJECT ? singletonObject : null);}

3、getObjectForBeanInstance方法

	protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {//如果name是以&开头的 但是不是FactoryBean,则直接抛出异常if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}// 则beanInstance可能是一个普通的bean,也可能是一个FactoryBean// 如果是一个普通的bean,则直接返回if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}//FactoryBean创建出bean实例返回Object object = null;if (mbd == null) {object = getCachedObjectForFactoryBean(beanName);}if (object == null) {FactoryBean<?> factory = (FactoryBean<?>) beanInstance;if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);}boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}

 

三、流程图

通过流程图我们可以更加直观的看出,getBean()方法的主要流程。

 


http://chatgpt.dhexx.cn/article/QV3EVacE.shtml

相关文章

getBean方法(一)

我们先看看这个方法的轮廓流程 这个getbean的轮廓方法很长. 先分两种情况: 一种是在缓存实例中能拿到bean, (主要是factroyBean的处理, 执行所有已注册的 BeanPostProcessor 的 postProcessAfterInitialization 方法) 前边是校验 (如果name以“&”为前缀&#xff0c;但是b…

Spring源码分析之getBean主流程分析

当我们通过向Spring容器获取某个bean的时候&#xff0c;总是调用Spring中重载的各种getBean方法。那么&#xff0c;getBean中的流程是什么样的&#xff1f; 通过本文&#xff0c;你将对getBean方法的主流程有一个详细的认识。 入口当然是getBean方法&#xff1a; public Obje…

getBean( )流程

getBean() 方法是顶层接口 BeanFactory 提供的&#xff0c;一共五个原型。AbstractBeanFactory作为抽象实现&#xff0c;复写了其中3个方法&#xff0c; Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}Overr…

Prometheus监控MongoDB数据库

监控环境&#xff1a;Prometheus 数据库&#xff1a;MongoDB 3.4.6 集群&#xff0c;3个节点 监控工具&#xff1a;mongodb_exporter 我这个模板是自己二次开发的。使用mongodb_exporter 监控 阿里云的MongoDB数据库 各位根据自己的需求进行使用 1、创建Mongodb监控可读账…

DBeaver 数据库管理工具

DBeaver 数据库管理工具 DBeaver 是一个基于 Java 开发&#xff0c;免费开源的通用数据库管理和开发工具&#xff0c;使用非常友好&#xff0c;且遵循ASL 协议。由于 DBeaver 基于 Java 开发&#xff0c;可以运行在各种操作系统上&#xff0c;比如Windows、Linux、macOS 等操作…

mysql数据库监控

MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Database Management System&#xff0c;关系数据…

一些数据库监控,优化,管理工具

http://www.itpub.net/viewthread.php?tid1057814&extra&page1 一些数据库监控,优化,管理工具 ******************************************************************* 这两天网盘连不上了&#xff0c;导致国内用户暂时无法下载。大家下载时需要用代理。这里提供一个比…

oracle实时监控工具

oracle实时监控工具市面上不多&#xff0c;但是兼具数据维护管理及性能实时监控的工具可以说更少&#xff0c;而实时监控又是项目运维管理&#xff0c;测试&#xff0c;开发但环节不可少的功能&#xff0c;目前有一款JAVA开发的&#xff0c;基于WEB的&#xff1a;TreeSoft数据库…

数据库的可用监控

监控 数据库是否连接和读写以及数据库的连接数 1、确认数据库是否可以通过网络连接 造成连接不成功的原因&#xff1a;防火墙 TCP/IP连接被占满 监控的方式&#xff1a; 1、mysqladmin -u 监控用户 -p 密码 -h 监控的服务器地址 ping 首先我们在MySQL下要建立一个mysql 的用户…

数据库实时监控,实时监控数据库数据

为了满足大多数用户对数据库的监控和运维需求&#xff0c;系统实时采集了监控数据库的主要指标&#xff0c;并提供完整的报警、性能容量分析和报告功能。  系统以数字形式收集现场设备发送的数据&#xff0c;通过实时数据操作实现监控功能&#xff0c;并提供有利于监控生产过…

数据库监控工具SQL Monitor:可同时实现云和本地的SQL Server数据库监视

SQL Monitor提供了一个基于Web的监视&#xff0c;在桌面计算机和移动设备上实时地监控服务器的性能。使用SQL Monitor时&#xff0c;只要一出现问题&#xff0c;你将会通过邮件和用户界面接收到警告&#xff0c;SQL Monitor会快速地做全局检查&#xff0c;检查单机&#xff0c;…

mysql实时监控工具

mysql实时监控工具市面上有许多了&#xff0c;但是兼具数据维护管理及性能实时监控的工具不多&#xff0c;可以说很少&#xff0c;而实时监控又是项目运维管理&#xff0c;测试&#xff0c;开发但环节不可少的功能&#xff0c;目前有一款JAVA开发的&#xff0c;基于WEB的&#…

数据库监控

数据库监控 一、数据库监控介绍 1、对什么进行监控 (1) 对数据库服务可用性进行监控 数据库进程或是端口存在并不意味着数据库就是可用的&#xff1b; 通过网络连接到数据库并且确定数据库是可以对外提供服务的。 (2) 对数据库性能进行监控 QPS和TPS&#xff1b; 并发线程数量…

MySQL - 数据库的监控方式

对于当前数据库的监控方式有很多&#xff0c;分为数据库自带、商用、开源三大类&#xff0c;每一种都有各自的特色&#xff1b; 而对于 mysql 数据库由于其有很高的社区活跃度&#xff0c;监控方式更是多种多样&#xff0c;不管哪种监控方式最核心的就是监控数据&#xff0c;获…

现在的SQLSERVER数据库监控软件有哪些?

现在的SQLSERVER数据库监控软件有哪些&#xff1f; 收集了一下当前SQLSERVER数据库监控软件&#xff0c;发现开源免费的真的是“没有” Questsoftware Quests spotlight&#xff08;收费&#xff09; http://www.quest.com/search/search-results.aspx?qspotlight Ideras S…

2019年最好用的6款数据库监控工具

为了让数据发挥最大的价值&#xff0c;通常我们都会采用数据库监控工具&#xff0c;本文将为大家介绍 6 款最好用的数据库监控工具。 "数据就是一切&#xff01;"我们都曾听过这种大胆的说法&#xff0c;但其实事实真是这样&#xff0c;而且数据还无处不在。如今&…

2019 年最好用的 7 款数据库监控工具

活动预告&#xff1a;数据库百家争鸣的背景下&#xff0c;Oracle究竟值不值得继续学习&#xff1f;未来Oracle DBA向何处去&#xff1f;如何在新的环境下站稳脚跟&#xff1f; 本周六&#xff0c;在北京将迎来一年一度的 ACOUG年会&#xff0c;在本次年会上&#xff0c;行业技术…

【正版软件】Navicat Monitor 实时数据库监控工具,一套安全、简单而且无代理的远程服务器监控工具。

简言 Navicat Monitor 是一套安全、简单而且无代理的远程服务器监控工具。它具有强大的功能使你的监控发挥最大效用。受监控的服务器包括 MySQL、MariaDB 和 SQL Server&#xff0c;并与 Amazon RDS、Amazon Aurora、Oracle Cloud、Microsoft Azure、阿里云、腾讯云和华为云等…

数据库监控工具

数据库监控是Applications Manager重要功能之一&#xff0c;它能够帮助数据库管理员(DBA)和系统管理员监控包含Oracle、SQL Server、MySQL、Sybase、IBM DB2等多种类异构型的数据库环境。作为无代理的数据库监控工具&#xff0c;Applications Manager通过执行数据库查询来采集性…

最好用的数据库监控工具和数据库知识

数据库监控的目的&#xff1f; 数据库监控的主要目标是确保数据在需要时是可用的。这听起来很简单&#xff0c;但实际操作却相当复杂&#xff0c;部分原因在于组件的数量和种类。从硬件到软件&#xff0c;数据库监控工具必须始终确保所有组件都是可用的&#xff0c;并且在正常…