getBean方法源码

news/2024/4/30 1:09:56/文章来源:https://blog.csdn.net/lmj3732018/article/details/126915389

一、 三个API

// 根据name获取bean	
@Override
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
}// 根据name获取bean,如果获取到的bean和指定类型不匹配,则抛出异常
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {return doGetBean(name, requiredType, null, false);
}// 根据name获取bean,如果是一个有参构造器生成的bean,则将参数对象注入到构造器中
@Override
public Object getBean(String name, Object... args) throws BeansException {return doGetBean(name, null, args, false);
}

二、源码

2.1. 获取name获取bean的真名,一个bean可以定义多个别名,这里会从map中递归获取到真名。  
2.2  根据beanName去单例池获取bean,如果存在直接返回。


   3. 如果单例池不存在bean,判断当前beanFactory是否有父的beanFactory,并且当前beanFactory能不能找到bean,如果当前beanFactory找到bean直接从当前beanFactory寻找后返回bean。否则则去父的bean工厂取。


   4. 真正的获取bean逻辑

   4.1 根据beanName得到合并后的beanDefinition

   4.2 判断得到的beanDefinition是否是抽象bean,是则抛异常


   5. 判断beanDefinition有没有@dependentOn注解,如果有,则判断被依赖的对象是否又依赖了当前beanDefinition,即出现了自定义的循环依赖,如果是则抛异常。
   6. 如果有@dependentOn但没有循环依赖,则将依赖的对象加入dependentOnMap中,dep为key你,beanName为value。再接着先完成依赖对象的getbean();


   7. 根据合并后的beanDefinition的作用域来真正创建bean对象。

      7.1 如果是单例bean,创建bean后将bean添加到单例池。

      7.2 如果是原型bean,创建bean后将直接返回。

      7.3 其他类型的作用域如request、session等则是基于HttpRequest、HttpSession等来实现bean的存储的。

 三、createBean源码

   3.1. 加载类
   3.2. 将合并后的beanDefinition的Beanclass属性设置为加载的类。


   3. 进行实例化前操作:有定义实现了InstantiationAwareBeanPostProcessor接口的实现类,则可对每个对象进行实例化前操作,即调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(),如果实例化前方法有返回对象,则直接返回,否则进入下一步。

 

    4. 实例化:
    4.1 判断当前bean是否已在别的bean创建过程中被创建了(被别的bean依赖注入)。如果没有则真正的创建bean。
    4.2 推断构造方法:
   5. 判断是否有实现了MergedBeanDefinitionPostProcessor.postProcessMergedInstantiation(),如果有通过它来修改beanDefinition的值。    

 
   5. 进行实例化后操作:有定义InstantiationAwareBeanPostProcessor接口的实现类,则可对每个对象进行实例化后操作,即调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),如果实例化后方法返回false,则直接返回,否则进入下一步。


   6. 属性的依赖注入:
    6.1 执行spring自带的属性注入,即@Bean(Autowired.BY_NAME)这种。Autowired.BY_NAME是根据set方法名去找。


    6.2 执行@Autowired、@Resource、@Value注解,如果到这一步之前已经给属性赋值了则跳过这一步,因为有可能程序员手动赋值了。没有则是通过InstantiationAwareBeanPostProcessor.postProcessProperties()实现。@Autowired、@Resource、@Value注解都是通过实现了InstantiationAwareBeanPostProcessor接口来处理的。
   7. 依赖注入完后就是初始化操作,分为四步:

   7.1 Aware回调,如果bean实现了Aware或其子接口,则会进行Aware的回调。

   7.1 初始化前,同初始化后一样是通过BeanPostProcessor机制实现的。

   7.2. 初始化,这里如果bean实现了InitializingBean接口,则会调用它的afterPropertiesSet()方法

   7.3. 初始化后

   8.  销毁方法,在初始化后还有最后一步,就是收集bean的销毁方法信息,将其加入disposableBeans中(一个LinkedHashMap)

1. 当前Bean是否实现了DisposableBean接口
2. 或者,当前Bean是否实现了AutoCloseable接口
3. BeanDefinition中是否指定了destroyMethod
4. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
    i. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
   ii. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是
DisposableBean
5. 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入
disposableBeans中(一个LinkedHashMap)
在Spring容器关闭过程时:
1. 首先发布ContextClosedEvent事件
2. 调用lifecycleProcessor的onCloese()方法
3. 销毁单例Bean
   i. 遍历disposableBeans
    a. 把每个disposableBean从单例池中移除
    b. 调用disposableBean的destroy()
    c. 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
    d. 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉
(inner bean参考https://docs.spring.io/spring-framework/docs/current/spring-
framework-reference/core.html#beans-inner-beans)
   ii. 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_9922.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++11 - 8 -智能指针

C11 - 智能指针前言&#xff1a;普通指针&#xff1a;安全隐患&#xff1a;其他函数异常&#xff1a;new函数异常&#xff1a;智能指针&#xff1a;RAII原理&#xff1a;smart_ptr&#xff1a;auto_ptr&#xff1a;管理权转移&#xff1a;优点&#xff1a;缺点&#xff1a;uniq…

报告分享|2022汽车生态营销白皮书

报告链接&#xff1a;http://tecdat.cn/?p28679 不确定性增加&#xff0c;消费意愿在压力下等待释放 今年3月以来&#xff0c;受国际冲突和国内环境双重影响&#xff0c;能源价格大幅上涨&#xff0c;导致全球供应不稳定趋势加深&#xff0c;宏观经济下行压力明显&#xff0…

程序设计竞赛-过了这个村没这个店

文章目录个人经验竞赛简介蓝桥杯天梯赛CCPCICPC其他个人经验 初闻不知曲中意&#xff0c;再闻已是曲中人。 标题无意夸张&#xff0c;但是竞赛生涯的时间真的不长&#xff0c;机会真的错过了就没有了。一般来说&#xff0c;大一打基础&#xff0c;学习编程语言、数据结构和算法…

Moment.js的常用函数、借助vue和Moment.js实现一个简单的时钟

前言 项目中关于时间的处理是挺常见的&#xff0c;虽然之前就知道有Moment.js这个库&#xff0c;但是一直没有接触过。只不过最近同事在项目中使用了&#xff0c;那也只能简单学习一下&#xff0c;不然遇到了完全看不懂。 本文只介绍一下常用的函数&#xff0c;其他内容可以在…

想换工作?那还不赶紧来看看这份面试题

引言 “寒冬”之下&#xff0c;诸如 “Android 凉了”之类的话我已经屡见不鲜了&#xff0c;现在互联网行业的热潮已经褪去&#xff0c;开始恢复冷静&#xff1b;这样一来&#xff0c;互联网公司就会面向大量的开发者们&#xff0c;因此对应的要求只会越来越高&#xff1b;据反…

用纯css实现一个图片拼接九宫格

<style> body{ margin: 0; padding: 0; // 设定居中 display: flex; justify-content: center; align-items: center; height: 100vh; } .container{ width: 300px; height: 300px; display: flex; // 子盒子布局&#xff0c;要让子盒子之间有间隙就把宽高设大一些。 jus…

报告分享|2022年中国机器人产业图谱及云上发展研究报告

报告链接&#xff1a;http://tecdat.cn/?p28681 报告在分析当前我国机器人市场现状与产业图谱的基础上&#xff0c;对人工智能、5G、云计算、边缘计算等新兴技术赋能机器人智能化、轻量化、柔性化发展进行了理性探讨&#xff0c;结合阿里云加速器企业案例探讨了机器人企业的上…

连接查询-mysql详解(五)

上篇文章说了&#xff0c;mysql5.6.6版本之前数据默认在系统表空间&#xff0c;之后默认在独立表空间&#xff0c;innodb因为索引和数据在一个b树&#xff0c;所以两个文件&#xff0c;一个文件结构&#xff0c;一个存数据&#xff0c;myISAM则是三个文件。一个聚簇索引有两个段…

小程序云开发学习笔记

小程序云开发学习笔记 初始化 在app.js里面 小程序一开始就初始化&#xff0c;多次调用只有第一次触发 onLaunch() { console.log("小程序打开"); wx.cloud.init({ env: ayang-8g50ew302a3a6c5a, //云开发id }) } 数据库操作 查询&#xff08;一定要配置数据权限&a…

高等工程数学 —— 第一章 (1)距离与范数

前言 研一生活开始了&#xff0c;看了大家对我之前博客的鼓励让我知道写博客是一件多么有意义的事情。写这些让我遇见许多陌生的有缘人&#xff0c;有老骥伏枥的大叔、也有可爱温暖的学妹…… 这里将高等工程数学的笔记留给不爱吃香菜的月亮&#xff0c;希望这些陪伴过我的微光…

ElasticSearch(四)【高级查询】

四、高级查询 说明 ES中提供了一种强大的检索数据方式&#xff0c;这种检索方式称之为Query DSL&#xff0c;Query DSL是利用Rest API传递JSON格式的请求体&#xff08;Request Body&#xff09;数据与ES进行交互&#xff0c;这种方式的丰富查询语法让ES检索变得更强大&#xf…

Grafana alert预警+钉钉通知

1 Grafana alert预警 如下图所示&#xff0c;主要是前3步&#xff0c;设置alert rules、contact points 、notification policies。alert rules主要设置触发警告的规则&#xff1b;contact points设置通过什么发送预警&#xff0c;如钉钉&#xff1b;notification policies 将…

哲学家干饭问题 C++

哲学家干饭问题 C 哲学家就餐问题可以这样表述&#xff0c;假设有五位哲学家围坐在一张圆形餐桌旁&#xff0c;做以下两件事情之一&#xff1a;吃饭&#xff0c;或者思考。吃东西的时候&#xff0c;他们就停止思考&#xff0c;思考的时候也停止吃东西。餐桌上有五碗意大利面&am…

Vue2.0到3.0的过渡,setup,ref函数,reactive函数,计算属性computed

setup 1、Vue3.0的组件中所有用到的:数据、方法等等&#xff0c;均要配置在setup中&#xff0c;若要使用里面的数据&#xff0c;可以用return将其返回出来 2、若在setup中返回的是一个对象&#xff0c;则对象中的数据、方法、在模板中均可直接使用 例如 <template><di…

[Git] 系列三随意修改提交记录以及一些技巧

[Git] 系列三随意修改提交记录以及一些技巧 Author: Xin Pan Date: 2022.09.17 文章目录[Git] 系列三随意修改提交记录以及一些技巧整理提交记录未知提交号哈希值时怎么办&#xff1f;一些技巧本地栈式提交方法一方法二TagDescribe高级命令总结好了&#xff0c;大概总结好了。…

搭建游戏要选什么样的服务器?

服务器是游戏平台数据传输的重要载体&#xff0c;事关我们游戏创业发展的稳定性、安全性。那么&#xff0c;游戏平台搭建要选什么服务器&#xff1f;有什么参考指标&#xff1f;本文将带领大家一探究竟&#xff01; 首先是“游戏平台搭建要选择什么服务器”&#xff0c;我们可…

论文阅读_对比学习_SimCSE

英文题目&#xff1a;SimCSE: Simple Contrastive Learning of Sentence Embeddings 中文题目&#xff1a;SimSCE&#xff1a;用简单的对比学习提升句嵌入的质量 论文地址&#xff1a;https://export.arxiv.org/pdf/2104.08821.pdf 领域&#xff1a;自然语言处理&#xff0c;对…

Redis的基本使用

1.Redis简介 &#xff08;1&#xff09;什么是Redis ①Redis是一个基于内存的key-value结构数据库 ②基于内存存储&#xff0c;读写性能高 ③适合存储热点数据(热点商品、资讯、新闻) ④Redis是一个开源的内存中的数据结构存储系统&#xff0c;它可以用作&#xff1a;数据库、…

计组--存储系统

存储系统 思维导图&#xff1a; 存储器概述 存储器的分类 按在计算机中的作用(层次)分类 主存储器&#xff0c;简称主存(内存) 存放计算机运行期间所需的程序和数据&#xff0c;CPU可以直接对其进行访问。 辅助存储器&#xff0c;简称辅存(外存) 辅存的内容需要调入主存后才…

普中A6开发版——XPT2046四引脚切换测量(含详细教程以及原理图等资料)

文章目录一、简介二、原理图以及手册三、接线四、选择数码管芯片原理讲解五、代码一、简介 本文介绍了XPT2046的使用方法以及普中A6开发版的接线等&#xff0c;并从原理图以及手册中摘选了详细的介绍&#xff0c;充分理解其工作原理。XPT2046本来是一个电阻式触摸屏控制器&…