文章目录:

  1. beanFactory 及 bean 生命周期起步
  2. BeanFactory refresh 全过程
  3. BeanFactoryPostProcessor 和 BeanPostProcessor 解析
  4. 使用 BeanPostProcessor 实现 aop 和 springboot Cache 相关注解实现
  5. 【本文】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 是真正查找这些注解的地方,最后 checkConfigMembersMember 注册进了 bean 定义,具体如何查找的读者自行查看源码。

这里只是将 Member 注册进了 bean 定义,真正实例化在填充 Bean 的过程中,下面说到 bean 的创建过程可以知道是何时注入的。

Bean 的创建过程

前面说到 spring 是在 getBean 的过程中进行 Bean 创建的,创建 bean 分为几个步骤

  1. 获取 bean 定义
  2. new Bean()
  3. 执行生命周期函数 (前)
  4. 创建依赖项
  5. 填充 bean
  6. 执行生命周期函数(后)

入口为 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. 1.spring:helloword/注入/CDATA使用/其他Bean/null&级联/p命名空间

    新建工程,导入jar,添加spring配置文件(配置文件xxxx.xml)! 1.Helloword实现 Helloword.java public class HelloWord { private ...

  2. 向Spring 容器中注入对象的几种方法

    1.使用@Bean 注解,用于注入第三方 jar 包到SpringIOC容器中. 2.使用 @Import({Order.class, Member.class, MyImportBeanDefini ...

  3. Spring基础知识1--环境搭建、bean创建、依赖注入、注解注入

    一.Spring两大核心内容 1.控制反转IOC/DI:  应用本身不负责对象的创建和维护,对象和依赖对象的创建完全交给容器管理. 2.AOP(面向切面编程):通过预编译的方式,在运行期通过动态代理的 ...

  4. spring源码深度解析— IOC 之 bean 创建

    在 Spring 中存在着不同的 scope,默认是 singleton ,还有 prototype.request 等等其他的 scope,他们的初始化步骤是怎样的呢?这个答案在这篇博客中给出. s ...

  5. Spring Boot Autowirted注入找不到Bean对象解决方法

    报错:Consider defining a bean of type 'xxxxxxxxxxxxx' in your configuration 1. 你应该在 ApplyApplication 启 ...

  6. Spring根据XML配置文件注入对象类型属性

    这里有dao.service和Servlet三个地方 通过配过文件xml生成对象,并注入对象类型的属性,降低耦合 dao文件代码: package com.swift; public class Da ...

  7. 一步一步深入spring(3)--spring的依赖注入方式

    对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则需要通过依赖注入方式,所谓的依赖注入就是通过spring将bean所需要的一些参数传递到bean实例对象的过程,sprin ...

  8. #Spring实战第二章学习笔记————装配Bean

    Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...

  9. Spring学习-依赖注入

    Spring是基于IOC与AOP的框架,而其中的IOC(Inversion of Control)即反转控制是Spring的基础. 在以前学过的知识中,一个新的对象全部为自己手动new出来的,而在Sp ...

随机推荐

  1. C# MQTT mqtt客户端,发布订阅消息

    如果想用C#来和mqtt的服务器进行数据交互的话,有一个常见的选择,那就是 MQTTNET 地址如下:https://github.com/chkr1011/MQTTnet 那个库在最近几个版本升级的 ...

  2. drf框架接口文档

    drf框架接口文档 REST framework可以自动帮助我们生成接口文档. 接口文档以网页的方式呈现. 自动接口文档能生成的是继承自APIView及其子类的视图. 一.安装依赖 pip insta ...

  3. django-drf框架中排序和查询组件

    0910自我总结 django-drf框架中排序和查询组件 一查询相关 1.模糊查询 1.导入模块组件 from rest_framework.filters import SearchFilter ...

  4. Java应用在docker环境配置容器健康检查

    在<极速体验docker容器健康>一文已体验了docker容器健康检查功能,今天就来给java应用的容器加入健康检查,使应用的状态随时都可以被监控和查看. 实战环境信息 操作系统:macO ...

  5. 非确定的自动机NFA确定化为DFA

    摘要: 在编译系统中,词法分析阶段是整个编译系统的基础.对于单词的识别,有限自动机FA是一种十分有效的工具.有限自动机由其映射f是否为单值而分为确定的有限自动机DFA和非确定的有限自动机NFA.在非确 ...

  6. ARToolKit-unity

    ARToolKit为开源的AR库,相对于高通和easyAr有几点特点: 1)开源 2)识别项目可以动态添加(详细在后) 3)识别文件可以本地生成 4)目前只能识别图片(目前为.jpg格式) 下边开始详 ...

  7. 如何用好redis pipeline

    编者注:pipeline是Redis的一个提高吞吐量的机制,适用于多key读写场景,比如同时读取多个key的value,或者更新多个key的value.工作过程中发现挺多小伙伴都对pipeline多少 ...

  8. vue设置页面标题

    使用vue-wechat-title插件对页面标题进行设置 1.安装模块    命令行窗口中运行npm install vue-wechat-title --save PS.如果程序正在运行,ctrl ...

  9. ABP WebApi的请求类型

    Api对应的请求类型分为以下四种方法: 1.POST 2.PUT 3.DELETE 4.GET 一般abp的请求类型都是根据接口命名来定义的,Create——POST,Delete——DELETE,U ...

  10. Linux 命令之 crontab

    crontab 简介 crontab 主要用于需要管理周期执行定时任务的场景 crontab 安装 (有些系统默认已经带了 crontab,无需安装的朋友可以直接跳过本节) 安装: yum insta ...