SpringIOC之创建Bean的核心方法doGetBean
创始人
2024-05-24 13:04:48
0

概述

面向资源(XML、Properties)、面向注解定义的 Bean 是如何被解析成 BeanDefinition(Bean 的“前身”),并保存至 BeanDefinitionRegistry 注册中心里面,实际也是通过 ConcurrentHashMap 进行保存。

Spring 底层 IoC 容器 DefaultListableBeanFactory,实现了 BeanFactory 和 BeanDefinitionRegistry 接口,这个时候它处于“就绪状态”,当我们显示或者隐式地调用 getBean(...) 方法时,会触发加载 Bean 阶段,获取对应的 Bean。在该方法中,如果是单例模式会先从缓存中获取,已有则直接返回,没有则根据 BeanDefinition 开始创建这个 Bean。

主体流程:getBean doGetBean createBean doCreateBean createBeanInstance、instantiate、populateBean、initializeBean、registerDisposableBeanIfNecessary(注册销毁方法)

BeanFactory 体系结构

下来熟悉下Sprig容器BeanFactory的体系

  • org.springframework.beans.factory.BeanFactory,Spring IoC 容器最基础的接口,提供依赖查找单个 Bean 的功能

  • org.springframework.beans.factory.ListableBeanFactory,继承 BeanFactory 接口,提供依赖查找多个 Bean 的功能

  • org.springframework.beans.factory.HierarchicalBeanFactory,继承 BeanFactory 接口,提供获取父 BeanFactory 的功能,具有层次性

  • org.springframework.beans.factory.config.ConfigurableBeanFactory,继承 HierarchicalBeanFactory 接口,提供可操作内部相关组件的功能,具有可配置性

  • org.springframework.beans.factory.config.AutowireCapableBeanFactory,继承 BeanFactory 接口,提供可注入的功能,支持依赖注入

  • org.springframework.beans.factory.config.ConfigurableListableBeanFactory,继承上面所有接口,综合所有特性,还提供可提前初始化所有单例 Bean 的功能

org.springframework.beans.factory.support.DefaultListableBeanFactory,Spring 底层 IoC 容器,依赖注入的底层实现

getBean(String name) 方法,根据名称获取 Bean,当然还有许多重载方法

最终都会调用

doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) 方法

下面是编程方法获取Bean对象的方法

       // 创建 BeanFactory 容器DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);// XML 配置文件 ClassPath 路径String location = "classpath:dependency-lookup-context.xml";// 加载配置int beanDefinitionsCount = reader.loadBeanDefinitions(location);System.out.println("Bean 定义加载的数量:" + beanDefinitionsCount);// 依赖查找System.out.println(beanFactory.getBean("user","1","jack2"));

按照这个代码调试整理成下图的流程图

下图是关于doGetBean 方法这一层的执行逻辑。其他的核心方法后面在更新文章。

总结

  • 可以看到这个方法加载 Bean 的过程中,会先从缓存中获取单例模式的 Bean;

  • 不管是从缓存中获取的还是新创建的,都会进行处理,如果是 FactoryBean 类型则调用其 getObject() 获取目标对象;

  • BeanFactory 可能有父容器,如果当前容器找不到 BeanDefinition 则会尝试让父容器创建;

  • 创建 Bean 的任务交由 AbstractAutowireCapableBeanFactory 去完成;

  • 如果获取到的 Bean 不是我们想要类型,会通过类型转换机制转换成目标类型

获取 beanName

从缓存中获取单例 Bean

FactoryBean 的处理

非单例模式依赖检查

BeanFactory 层次性加载 Bean 策略

将 beanName 标记为已创建

获取 RootBeanDefinition

依赖 Bean 的处理

不同作用域的 Bean 的创建

单例模式

多例模式

其他模式

过程如下:

  1. 从当前容器获取该模式的 Scope 对象 scope,不存在则抛出异常

  1. 从 scope 中获取 beanName 对应的对象(看你的具体实现),不存在则执行原型模式的四个步骤进行创建

想要自定义一个作用域,可以实现 org.springframework.beans.factory.config.Scope 接口,并往 Spring 应用上下文注册即可 这个也是一个拓展接口

类型转换

如果入参 requiredType 不为空,并且 Bean 不是该类型,则需要进行类型转换,过程如下:

  1. 通过类型转换机制,将 Bean 转换成 requiredType 类型,对 Spring 的类型转换机制参考 org.springframework.core.convert.support.DefaultConversionService

我们也可以基于此做拓展的。

  1. 转换后的 Bean 为空则抛出异常

  1. 返回类型转换后的 Bean 对象

归纳拓展

对 BeanFactory 接口的体系结构进行了分析,得知 DefaultListableBeanFactory 是 BeanFactory 的最底层实现,也就是 Spring 的底层 IoC 容器。接着分析了 AbstractBeanFactory 的 getBean(...) 方法,当我们显示或者隐式地调用这个方法时,会触发 Bean 的加载。上面对 Bean 的加载过程进行了分析。

不同作用域的 Bean 的创建,底层都会调用 AbstractAutowireCapableBeanFactory 的 createBean(...)方法进行创建,创建 Bean 的过程涉及到 Bean 生命周期的大部分阶段,例如实例化阶段、属性赋值阶段、Aware 接口回调阶段、初始化阶段都是在这个方法中完成的。

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...