spring 是如何注入对象的和bean 创建过程分析

文章目录:

首先需要知道一个大致实现

  • 这个注入过程肯定是在 BeanPostProcessor 中实现的
  • spring 是在 beanFactory.getBean 进行 bean 实例化的,即懒加载
  • 根据第二条,也就是说在 getBean 的时候才会去调用所有 BeanPostProcessor
  • 第二篇文章说到,BeanFactory 的 refresh 过程只是注册 BeanPostProcessor,真正执行在 getBean 方法中
  • MergedBeanDefinitionPostProcessor 也是一种 BeanPostProcessor 它重新弄了个一个生命周期函数,替代了 BeanPostProcessor 默认的生命周期函数,这么看吧,我贴一小段源码
for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof MergedBeanDefinitionPostProcessor) {
        MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
        bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
}

它允许你在非 BeanFactoryProcess 中去修改 Bean 定义
* InstantiationAwareBeanPostProcessor 也是一种 BeanPostProcessor 它也重新定义了一个生命周期函数,它允许把属性值注入到属性对象中

我们先不看 bean 的创建过程,就看 MergedBeanDefinitionPostProcessor 的实现子类,这里看名字猜测 AutowiredAnnotationBeanPostProcessor 应该就是干这件事的,所以我们接下来可以直接看 AutowiredAnnotationBeanPostProcessor 的 postProcessMergedBeanDefinition 方法的代码。

顺着方法的调用,可以知道在 buildAutowiringMetadata 是真正查找这些注解的地方,最后 checkConfigMembersMember 注册进了 bean 定义,具体如何查找的读者自行查看源码。

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

前面说到 spring 是在 getBean 的过程中进行 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);

最终的处理过程在 AutowiredAnnotationBeanPostProcessor 的 postProcessPropertyValues 函数中

metadata.inject(bean, beanName, pvs);

因为在前面已经获取过依赖项,并且把其丢进了容器,所以这里是直接用反射写进去就可以了

创建 bean 第四步,初始化 bean ,这里有一个方法注入,方法注入原来发生在初始化 bean 过程中,还有就是生命周期函数执行了,包含 BeanPostProcessor 的前置后置生命周期,初始化方法等

小说明 : AutowiredAnnotationBeanPostProcessor 即是 一个 MergedBeanDefinitionPostProcessor 也是一个 InstantiationAwareBeanPostProcessor

一点小推广

创作不易,希望可以支持下我的开源软件,及我的小工具,欢迎来 gitee 点星,fork ,提 bug 。

Original: https://www.cnblogs.com/sanri1993/p/11876644.html
Author: sanri1993
Title: spring 是如何注入对象的和bean 创建过程分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/569609/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Nginx: 解决反代时,超过1分钟Gateway Timeout 504问题

    打开Nginx的配置文件中,在对应的反代域名下,添加 proxy_connect_timeout 300;proxy_send_timeout 300;proxy_read_tim…

    Java 2023年5月30日
    075
  • 程序设计基础·Java学习笔记·集合

    一、集合 (一)Java集合 1.概述:Java集合类存放与java.util包中,是一个用来存放对象的容器; 2.特点:Java集合的特点 (1)集合只能存放对象;比如存放一个i…

    Java 2023年6月7日
    068
  • 统一网关Gateway的使用:

    为什么需要网关? Gateway网关是我们服务的守门神,所有微服务的统一入口 网关的核心功能特性: 网关的功能:身份认证和权限校验 服务路由,负载均衡 请求限流 在SpringCl…

    Java 2023年6月16日
    091
  • 线上接口经常超时,我用线程池+ FutureTask解决了,YYDS

    用线程池+ FutureTask将1个查询拆分成多个小查询 选择FutureTask是因为它具有仅执行1次run()方法的特性(即使有多次调用也只执行1次),避免了重复查询的可能。…

    Java 2023年5月30日
    0136
  • Spring Boot 启动源码解析结合Spring Bean生命周期分析

    转载请注明出处: 目录 1.SpringBoot 源码执行流程图 创建SpringApplication 应用,在构造函数中推断启动应用类型,并进行spring boot自动装配 …

    Java 2023年5月30日
    074
  • 记一次Idea无法打开记录(idea升级)

    记一次Idea无法打开记录 前言,本来今天是打算升级Idea,然后体验一波的,结果升级完之后,发现无法打开idea(双击之后并没有任何打开的反应)。 原因排查,打开idea所在目录…

    Java 2023年6月5日
    059
  • 深入理解Apollo核心机制之灰度发布——创建灰度

    概述 ApolloPortal创建灰度后都做了什么呢?Apollo是如何维护主版本与灰度版本关系的呢? 其实创建灰度非常简单,可以看到下图中”Cluster&#8221…

    Java 2023年6月6日
    067
  • 抽象类和接口,你了解多少?

    现在的java开发一般都说面向接口编程,在开发过程中使用的最多的是给service层每个方法写一个接口,如果用到了DAO层,那么也是一个Mapper接口,之后的事情就交给mybat…

    Java 2023年6月9日
    076
  • Callable接口

    Callable接口 特点 1.有返回 2.可以抛出异常 代码实现,Callable接口开启线程 public class CallableTest { public static…

    Java 2023年6月5日
    078
  • Java程序猿怎样高速理解Kubernetes

    我们希望微服务是可复制的。可替换的工作节点。这样能够轻松进行升级或降级,同一时候无需不论什么停机时间,并花费最少代价的管理。 我们能够说我们希望他们成为我们的小黄人(minions…

    Java 2023年5月29日
    073
  • Spring Boot 内置工具类 springboot

    对象、数组、集合 获取对象的基本信息 判断工具 其他工具方法 字符串判断工具 字符串操作工具 路径相关工具方法 集合判断工具 //java项目大全fhadmin.cn // 判断 …

    Java 2023年6月8日
    057
  • Kubernetes-PV-PVC

    1. 简介 持久卷(PersistentVolume,PV&#…

    Java 2023年6月7日
    068
  • Fluent-Validator 业务校验器

    在互联网行业中,基于Java开发的业务类系统,不管是服务端还是客户端,业务逻辑代码的更新往往是非常频繁的,这源于功能的快速迭代特性。在一般公司内部,特别是使用Java web技术构…

    Java 2023年6月9日
    073
  • 【java编程】vo、po、dto、bo、pojo、entity、mode如何区分

    Java Bean:一种可重用组件,即”一次编写,任何地方执行,任何地方重用”。满足三个条件 类必须是具体的和公共的 具有无参构造器 提供一致性设计模式的公…

    Java 2023年5月29日
    069
  • Java数组常见算法3——排序算法(冒泡排序、快速排序)

    Java数组的常见排序算法简介,两种主要的排序算法实现——冒泡排序、快速排序 排序算法简介 排序:对一序列对象根据某个关键字进行排序。 衡量排序算法的优劣: 时间复杂度:分析关键字…

    Java 2023年6月5日
    073
  • vue路由守卫用于登录验证权限拦截

    vue路由守卫用于登录验证权限拦截 to:进入到哪个路由去 from:从哪个路由离开 next:路由的控制参数,常用的有next(true)和next(false) home需要判…

    Java 2023年6月15日
    067
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球