阅读 Spring 源码,BeanFactory 是避不了的存在。而大家常见的使用场景,也是以下形式:

ConfigurableApplicationContext ctx = SpringApplication.run(xxx.class);
BeanFactory beanFactory = (BeanFactory) ctx;
beanFactory.getBean(xxx);

但 BeanFactory 可不是如此枯燥无味的。

前置知识

  1. Spring 的 IOC 特性的核心就是: Bean容器,也叫 Bean工厂 —— 存储 bean 的工厂,负责 bean 的加入、实例化、初始化、监控与删除操作。
  2. 我们知道,使用 Spring 前,我们需要在 XML 或 Annotation 中配置 bean,这样 Spring 在启动时,通过加载指定的配置文件或配置类,就能够往容器中存入相应的 bean 实例。而这些在配置文件/类中的定义,称为 Bean定义,在 Spring 中使用 BeanDefinition 进行封装。
  3. Bean定义所在的配置文件/配置类,我们称为配置源,Spring 支持不同的配置源,有:XML、Annotation、Groovy 甚至 Property。
  4. 读取不同的配置源,有不同的读取器,如:读取 XML 的有 XmlBeanDefinitionReader,读取 Property 的有 PropertiesBeanDefinitionReader,读取 Annotation 的有:AnnotatedBeanDefinitionReader。
  5. Annotation 是在 Java5 之后引入的,所以初期 Spring 以读取指定配置源来收集 Bean定义;在 Spring 支持注解之后,配置源由配置文件转变为 Class。所以,AnnotatedBeanDefinitionReader 与 XmlBeanDefinitionReader 并没有继承自统一父类,但他们属于相同的模块概念。

BeanFactory

在 Spring 中 BeanFactory 接口的定义非常简单,主要有以下方法:

<T> T getBean(Class<T> requiredType) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
// ...其他

只负责获取、判断操作。

然而,仅仅这些方法并不满足多功能 BeanFactory 的需求,所以 BeanFactory 有以下三个不同特性的子类:

ListableBeanFactory
HierarchicalBeanFactory
AutowireCapableBeanFactory
  • ListableBeanFactory:此子接口要求实现者具被枚举/索引/检索功能,从而避免需要通过 beanName 一个个迭代进行查找,我们很快就能想到 Map 结构。同时,此接口定义的方法,要求能够关注到预加载的BeanDefinition(即 Bean 定义)。
String[] getBeanDefinitionNames();
boolean containsBeanDefinition(String beanName);
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit);
  • HierarchicalBeanFactory:此类见名知意,是个具有层级结构的 BeanFactory,它提供的方法,也只有以下两个:获取父工厂及判断当前工厂是否包含指定 Bean。
BeanFactory getParentBeanFactory();
boolean containsLocalBean(String name);
  • AutowireCapableBeanFactory:此类是 Spring 提供的,用以支持 Bean 自动装配、注入、填充的工厂,也就是说 Bean 的实例化在此工厂中(常见的 Bean 的实例化的过程在此工厂中完成,定义了相关的 API)
<T> T createBean(Class<T> beanClass) throws BeansException;    // 创建
void autowireBean(Object existingBean) throws BeansException; // 自动装配
Object initializeBean(Object existingBean, String beanName) throws BeansException; // 初始化
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) BeansException; // 过程回调
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException; // 过程回调
void destroyBean(Object existingBean); // 销毁

乍一看,发现 BeanFactory 丰富了很多,与 BeanDefinition 也有了关联,可仔细一看,就会发现,这些接口定义的都是获取或判断方法,与 BeanFactory 类似;而且都是与 Bean 有紧密联系。在此之外,Spring 提供了 BeanFactory 的相关控制选项的配置接口

Spring 首先提供了一个 HierarchicalBeanFactory 的子类:ConfigurableBeanFactory。它定义了 BeanFactory 的一些相关配置入口,同时也定义了 HierarchicalBeanFactory#getParentBeanFactory 的parent设置入口,总的来说,它是 BeanFactory 配置的相关类(定义了配置的设置与获取),比如有:Scope 的注册、类型转换器列表的持有,后置处理器的新增等等,

void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;    // 设置父工厂
void setBeanClassLoader(@Nullable ClassLoader beanClassLoader); // 设置 Bean 的 ClassLoader
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); // 添加 BeanPostProcessor
void registerScope(String scopeName, Scope scope); // 注册 Scope
Scope getRegisteredScope(String scopeName); // 从 BeanFactory 获取配置的 Scope 信息
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; // 获取合并后的 BeanDefinition

工厂相关的配置有了。Spring 又在此基础上,扩展了一个新的子工厂类型:ConfigurableListableBeanFactory,它的继承关系如下:

此接口继承了所有 BeanFactory 相关的主要接口类型,具备了上述提及的工厂的所有功能,现在这个类型是“有闲有钱”,我们来看看它定义了哪些新方法:

void ignoreDependencyInterface(Class<?> ifc);    // 忽略依赖接口,如:Aware 类接口
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; // 获取Bean定义(只获取当前Bean内的定义,不考虑层级)
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException; // 是否支持自动注入
void freezeConfiguration(); // 冻结配置,Bean定义不再支持修改(修改意味着要重新生成Bean实例)
void preInstantiateSingletons() throws BeansException; // 与实例化所有单例

因为继承了自动配置工厂(AutowireCapableBeanFactory),因此具备自动装配Bean能力。同时自己在此基础上,定义了一层外部控制,如:isAutowireCandidate、freezeConfiguration,更重要的是:preInstantiateSingletons。

毕竟它现在掌握了资源:具备检索Bean定义、具备自动装配控制、具备Bean工厂配置,因此它有能力作为实例化单例的入口。

除了继承主要的 Bean工厂类型,此接口还继承了 SingletonBeanRegistry。此接口与其他接口没有任何关联,却与 Spring IOC 特性息息相关。

我们知道,Spring 容器中的 Bean 具备多种 Scope 范围,我们常见的是 Singleton、Prototype。但通过以上工厂定义,我们看到的只有 getBean 操作,而没有 getSingleton。也就是说:Spring 的顶层 BeanFactory 关注的的确只有 IOC(即控制反转),而不关注容器内是单例还是原型。要想通过 BeanFactory 来获知实例范围信息,只能通过其方法:isSingletonisPrototype。没错,就是这么纯粹。

因为单例模型在Spring中也是举足轻重,所以 Spring 划分了单独的概念:SingletonBeanRegistry

它的方法有:

void registerSingleton(String beanName, Object singletonObject);    // 注册单例(不一定要通过Bean定义构建)
Object getSingleton(String beanName); // 获取单例
boolean containsSingleton(String beanName); // 判断是否包含单例
String[] getSingletonNames(); // 获取所有单例名称
int getSingletonCount(); // 获取单例数

具备了单例的注册与获取。

当然,除非明确指定 bean 非单例,否则,在 Spring 中默认解析 Bean定义后注册到容器中,都是使用:registerSingleton,即默认注册单例类型。

以上结果,构建了一个功能丰富且完善的 Bean工厂,具有

  • Bean工厂 配置
  • BeanDefinition 索引获取
  • 触发实例化 Bean
  • Bean实例化与填充、初始化
  • Bean构建时回调
  • Bean实例索引获取
  • Bean销毁
  • 上溯获取父工厂

每个 Bean工厂都有相应的 Abstract实现,最终由子类:DefaultListableBeanFactory 完成统一大业,并被 ApplicationContext 使用

Bean 的构建基于 Bean定义,它从何而来?

Spring 为 BeanDefinition 定义了抽象 BeanDefinitionRegistry,具有以下方法:

void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);

具备 Bean定义的注册、移除、获取、判断等,并由 DefaultListableBeanFactory 进行实现。所以 DefaultListableBeanFactory 作为 Spring 的核心类 ApplicationContext 的内定工厂,实现如下:

总结:

  1. 了解了 BeanFactory 的继承体系之后,你能够很快地回忆起相关的知识点,比如:

    • Bean的实例化过程,那一定是在 AutowireCapableBeanFactory 中,而且默认实现就是抽象类:AbstractAutowireCapableBeanFactory
    • Bean工厂具有层级概念,当前 Bean工厂获取不到相应信息时(Bean实例、Bean定义等),可上溯父工厂获取;
  2. 如何较好地记忆 BeanFactory 相关知识点,可通过功能、命名等方面入手,如:

  3. 回顾源码,你会看到如下代码

只有相应的接口实现,才具备对应的 API 进行设置与获取。

以上是 Bean工厂的相关学习与总结,如果错漏,欢迎指正。

【Spring浅析】一、 BeanFactory 有啥可说的?的更多相关文章

  1. 转:Spring系列之beanFactory与ApplicationContext

    原文地址:Spring系列之beanFactory与ApplicationContext 一.BeanFactoryBeanFactory 是 Spring 的“心脏”.它就是 Spring IoC ...

  2. spring 简单实现BeanFactory(转)

    原文地址: http://blog.csdn.net/mlc1218559742/article/details/52776160 有没有发现上面的代码与利用反射实现工厂模式的代码很相似.对,你没有看 ...

  3. 44、[源码]-Spring容器创建-BeanFactory预准备

    44.[源码]-Spring容器创建-BeanFactory预准备 @Override public void refresh() throws BeansException, IllegalStat ...

  4. Spring中的BeanFactory与FactoryBean看这一篇就够了

    前言 理解FactoryBean是非常非常有必要的,因为在Spring中FactoryBean最为典型的一个应用就是用来创建AOP的代理对象,不仅如此,而且对理解Mybatis核心源码也非常有帮助!如 ...

  5. Spring系列之beanFactory与ApplicationContext

    一.BeanFactoryBeanFactory 是 Spring 的“心脏”.它就是 Spring IoC 容器的真面目.Spring 使用 BeanFactory 来实例化.配置和管理 Bean. ...

  6. [原创]java WEB学习笔记98:Spring学习---Spring Bean配置及相关细节:如何在配置bean,Spring容器(BeanFactory,ApplicationContext),如何获取bean,属性赋值(属性注入,构造器注入),配置bean细节(字面值,包含特殊字符,引用bean,null值,集合属性list map propert),util 和p 命名空间

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  7. 深入剖析 Spring 框架的 BeanFactory

    说到Spring框架,人们往往大谈特谈一些似乎高逼格的东西,比如依赖注入,控制反转,面向切面等等.但是却忘记了最基本的一点,Spring的本质是一个bean工厂(beanFactory)或者说bean ...

  8. spring中的BeanFactory与ApplicationContext的作用和区别?

    BeanFactory类关系继承图 1. BeanFactory类结构体系: BeanFactory接口及其子类定义了Spring IoC容器体系结构,由于BeanFactory体系非常的庞大和复杂, ...

  9. Spring学习笔记——Spring中的BeanFactory与FactoryBean

    BeanFactory BeanFactory是Spring的org.springframework.beans.factory下的一个接口,是Spring IOC所遵守的基本编程规范.他的实现类有D ...

随机推荐

  1. 从零学脚手架(八)---webpack-dev-server源码分析

    上一篇中介绍了webpack-dev-server属性配置 这一篇就简单的梳理下webpack-dev-server内部实现. 由于涉及到源码解析,所以会涉及到一些比较难啃的知识,我会尽量进行简单化描 ...

  2. Java类集框架详细汇总-底层分析

    前言: Java的类集框架比较多,也十分重要,在这里给出图解,可以理解为相应的继承关系,也可以当作重要知识点回顾: Collection集合接口 继承自:Iterable public interfa ...

  3. Java单例模式实现,一次性学完整,面试加分项

    单例模式是设计模式中使用最为普遍的一种模式.属于对象创建模式,它可以确保系统中一个类只产生一个实例.这样的行为能带来两大好处: 对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而 ...

  4. Istio最佳实践系列:如何实现方法级调用跟踪?

    赵化冰,腾讯云高级工程师,Istio Member,ServiceMesher 管理委员,Istio 项目贡献者,热衷于开源.网络和云计算.目前主要从事服务网格的开源和研发工作. 引言 TCM(Ten ...

  5. 「SpringBoot2.4新特性」jar自动瘦身

    自动分析瘦身 Spring Boot 项目最终构建处理 JAR 包大小一直是个诟病,需要把所有依赖包内置最终输出可运行的 jar. 当然可以使用其他的插件扩展 实现依赖 JAR 和 可运行 jar 分 ...

  6. 集群部署时的分布式session如何实现?

    session是啥?浏览器有个cookie,在一段时间内这个cookie都存在,然后每次发请求过来都带上一个特殊的jsessionid cookie,就根据这个东西,在服务端可以维护一个对应的sess ...

  7. idea无法引入自己定义的包和类

    方法一:通过清理缓存解决: File -> Invalidate Caches / Restart...,在新窗口点击Invalidte and Restart,未奏效 方法二:导入依赖 如图, ...

  8. 【笔记】《Redis设计与实现》chapter18 发布与订阅

    chapter18 发布与订阅 客户端订阅频道. 客户端向频道发送消息, 消息被传递至各个订阅者. 匹配模式 客户端订阅模式. 客户端向频道发送消息, 消息被传递给正在订阅匹配模式的订阅者. 另一个模 ...

  9. Linux入门之基本的概念、安装和操作

    目录 Linux基本概念 Linux的安装 虚拟机安装CentOS7 CentOS设置网络 Linux基本操作命令 文件目录操作命令 进程操作命令 文本操作命令 Linux权限操作 用户和组操作命令 ...

  10. 亮相 LiveVideoStackCon,透析阿里云窄带高清的现在与未来

    2021.4.16-4.17,阿里云视频云亮相 LiveVideoStackCon 音视频技术大会上海站,带来三场不同视角的主题演讲,并与众多行业伙伴一同交流.在 "编解码的新挑战与新机会& ...