spring 是如何注入对象的和bean 创建过程分析
文章目录:
- beanFactory 及 bean 生命周期起步
- BeanFactory refresh 全过程
- BeanFactoryPostProcessor 和 BeanPostProcessor 解析
- 使用 BeanPostProcessor 实现 aop 和 springboot Cache 相关注解实现
- 【本文】spring 是如何注入对象的
首先需要知道一个大致实现
这个注入过程肯定是在
BeanPostProcessor中实现的spring 是在
beanFactory.getBean进行 bean 实例化的,即懒加载根据第二条,也就是说在 getBean 的时候才会去调用所有
BeanPostProcessor第二篇文章说到,BeanFactory 的 refresh 过程只是注册
BeanPostProcessor,真正执行在 getBean 方法中MergedBeanDefinitionPostProcessor也是一种BeanPostProcessor它是专门用来处理注入的,如@Autowired和@Value,它重新弄了个一个生命周期函数,替代了BeanPostProcessor默认的生命周期函数,这么看吧,我贴一小段源码for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } }它允许你在非
BeanFactoryProcess中去修改 Bean 定义
@Autowired 加载定义的过程
我们先不看 bean 的创建过程,就看 MergedBeanDefinitionPostProcessor 的实现子类,这里看名字猜测 AutowiredAnnotationBeanPostProcessor 应该就是干这件事的,所以我们接下来可以直接看 AutowiredAnnotationBeanPostProcessor 的 postProcessMergedBeanDefinition 方法的代码。
顺着方法的调用,可以知道在 buildAutowiringMetadata 是真正查找这些注解的地方,最后 checkConfigMembers 将 Member 注册进了 bean 定义,具体如何查找的读者自行查看源码。
这里只是将 Member 注册进了 bean 定义,真正实例化在填充 Bean 的过程中,下面说到 bean 的创建过程可以知道是何时注入的。
Bean 的创建过程
前面说到 spring 是在 getBean 的过程中进行 Bean 创建的,创建 bean 分为几个步骤
- 获取 bean 定义
- new Bean()
- 执行生命周期函数 (前)
- 创建依赖项
- 填充 bean
- 执行生命周期函数(后)
入口为 BeanFactory.getBean ,BeanFactory 的实现类为 DefaultListableBeanFactory 这些你可以在 BeanFactory 的 refresh 过程中找到
根据源码,如果 bean 还不存在时,就会执行 bean 的创建流程
获取 bean 定义在这段源码中
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
紧跟着,根据 Bean 定义搜索其依赖项,并创建 bean ,可以看出是递归创建 bean
String[] dependsOn = mbd.getDependsOn();
for (String dep : dependsOn) {
getBean(dep);
}
然后就创建 bean 了
if (mbd.isSingleton()) {
createBean(beanName, mbd, args);
}
// 真正的执行在 doCreateBean 过程中
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
创建 bean 第一步 new Bean
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
创建 bean 第二步,执行所有的 processor ,包含 MergedBeanDefinitionPostProcessor ,所以在这一步注册注入选项
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
创建 bean 第三步,填充 bean ,这里做的 @Autowired 注入
populateBean(beanName, mbd, instanceWrapper);
深入源码可以看到这个
// 这里就是常说的根据名称注入,根据类型注入了
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
因为在前面已经获取过依赖项,并且把其丢进了容器,所以这里是直接用反射写进去就可以了
创建 bean 第四步,初始化 bean ,这里有一个方法注入,方法注入原来发生在初始化 bean 过程中,还有就是生命周期函数执行了,包含 BeanPostProcessor 的前置后置生命周期,初始化方法等
一点小推广
创作不易,希望可以支持下我的开源软件,及我的小工具,欢迎来 gitee 点星,fork ,提 bug 。
Excel 通用导入导出,支持 Excel 公式
博客地址:https://blog.csdn.net/sanri1993/article/details/100601578
gitee:https://gitee.com/sanri/sanri-excel-poi
使用模板代码 ,从数据库生成代码 ,及一些项目中经常可以用到的小工具
博客地址:https://blog.csdn.net/sanri1993/article/details/98664034
gitee:https://gitee.com/sanri/sanri-tools-maven
spring 是如何注入对象的和bean 创建过程分析的更多相关文章
- 1.spring:helloword/注入/CDATA使用/其他Bean/null&级联/p命名空间
新建工程,导入jar,添加spring配置文件(配置文件xxxx.xml)! 1.Helloword实现 Helloword.java public class HelloWord { private ...
- 向Spring 容器中注入对象的几种方法
1.使用@Bean 注解,用于注入第三方 jar 包到SpringIOC容器中. 2.使用 @Import({Order.class, Member.class, MyImportBeanDefini ...
- Spring基础知识1--环境搭建、bean创建、依赖注入、注解注入
一.Spring两大核心内容 1.控制反转IOC/DI: 应用本身不负责对象的创建和维护,对象和依赖对象的创建完全交给容器管理. 2.AOP(面向切面编程):通过预编译的方式,在运行期通过动态代理的 ...
- spring源码深度解析— IOC 之 bean 创建
在 Spring 中存在着不同的 scope,默认是 singleton ,还有 prototype.request 等等其他的 scope,他们的初始化步骤是怎样的呢?这个答案在这篇博客中给出. s ...
- Spring Boot Autowirted注入找不到Bean对象解决方法
报错:Consider defining a bean of type 'xxxxxxxxxxxxx' in your configuration 1. 你应该在 ApplyApplication 启 ...
- Spring根据XML配置文件注入对象类型属性
这里有dao.service和Servlet三个地方 通过配过文件xml生成对象,并注入对象类型的属性,降低耦合 dao文件代码: package com.swift; public class Da ...
- 一步一步深入spring(3)--spring的依赖注入方式
对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则需要通过依赖注入方式,所谓的依赖注入就是通过spring将bean所需要的一些参数传递到bean实例对象的过程,sprin ...
- #Spring实战第二章学习笔记————装配Bean
Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...
- Spring学习-依赖注入
Spring是基于IOC与AOP的框架,而其中的IOC(Inversion of Control)即反转控制是Spring的基础. 在以前学过的知识中,一个新的对象全部为自己手动new出来的,而在Sp ...
随机推荐
- C# MQTT mqtt客户端,发布订阅消息
如果想用C#来和mqtt的服务器进行数据交互的话,有一个常见的选择,那就是 MQTTNET 地址如下:https://github.com/chkr1011/MQTTnet 那个库在最近几个版本升级的 ...
- drf框架接口文档
drf框架接口文档 REST framework可以自动帮助我们生成接口文档. 接口文档以网页的方式呈现. 自动接口文档能生成的是继承自APIView及其子类的视图. 一.安装依赖 pip insta ...
- django-drf框架中排序和查询组件
0910自我总结 django-drf框架中排序和查询组件 一查询相关 1.模糊查询 1.导入模块组件 from rest_framework.filters import SearchFilter ...
- Java应用在docker环境配置容器健康检查
在<极速体验docker容器健康>一文已体验了docker容器健康检查功能,今天就来给java应用的容器加入健康检查,使应用的状态随时都可以被监控和查看. 实战环境信息 操作系统:macO ...
- 非确定的自动机NFA确定化为DFA
摘要: 在编译系统中,词法分析阶段是整个编译系统的基础.对于单词的识别,有限自动机FA是一种十分有效的工具.有限自动机由其映射f是否为单值而分为确定的有限自动机DFA和非确定的有限自动机NFA.在非确 ...
- ARToolKit-unity
ARToolKit为开源的AR库,相对于高通和easyAr有几点特点: 1)开源 2)识别项目可以动态添加(详细在后) 3)识别文件可以本地生成 4)目前只能识别图片(目前为.jpg格式) 下边开始详 ...
- 如何用好redis pipeline
编者注:pipeline是Redis的一个提高吞吐量的机制,适用于多key读写场景,比如同时读取多个key的value,或者更新多个key的value.工作过程中发现挺多小伙伴都对pipeline多少 ...
- vue设置页面标题
使用vue-wechat-title插件对页面标题进行设置 1.安装模块 命令行窗口中运行npm install vue-wechat-title --save PS.如果程序正在运行,ctrl ...
- ABP WebApi的请求类型
Api对应的请求类型分为以下四种方法: 1.POST 2.PUT 3.DELETE 4.GET 一般abp的请求类型都是根据接口命名来定义的,Create——POST,Delete——DELETE,U ...
- Linux 命令之 crontab
crontab 简介 crontab 主要用于需要管理周期执行定时任务的场景 crontab 安装 (有些系统默认已经带了 crontab,无需安装的朋友可以直接跳过本节) 安装: yum insta ...