Spring 基础容器 BeanFactory

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 什么是BeanFactory?Spring官网对BeanFactory的解释BeanFactory API 为Spring的IoC功能提供了底层基础。它的特定契约主要用于Spring的其他部分以及相关第三方框架其他部分的集成,它的DefaultListableBeanFactory实现是更高级别GenericApplicationContext容器的一个委托。

什么是BeanFactory?

Spring官网对BeanFactory的解释

BeanFactory API 为Spring的IoC功能提供了底层基础。它的特定契约主要用于Spring的其他部分以及相关第三方框架其他部分的集成,它的DefaultListableBeanFactory实现是更高级别GenericApplicationContext容器的一个委托。


BeanFactory和相关接口(例如BeanFactoryAware,InitializingBean,DisposableBean)是其他框架组件的重要集成点。不需要通过任何注解或甚至不需要反射,它们允许容器及其组件之间非常有效的交互。应用级别的bean可以使用相同的回调接口,但通常更偏好通过注解或通过程序配置进行声明式依赖注入。


请注意,核心BeanFactory API及DefaultListableBeanFactory实现不会假设要使用的配置格式或任何组件注解。这些都是通过扩展(例如XmlBeanDefinitionReader和AutowiredAnnotationBeanPostProcessor)引入的,并以核心元数据表示形式对共享的BeanDefinition对象进行操作。这就是使Spring的容器如此灵活和可扩展的本质。


BeanFactory源码注释

BeanFactory是用于访问Spring Bean容器的根接口,是bean容器的基本客户机视图;


其他接口,如ListableBeanFactory和ConfigurableBeanFactory可用于特定目的。


这个接口是由包含许多bean定义的对象实现的,每个bean定义都由一个字符串名称唯一标识。根据bean定义,工厂将返回包含对象的独立实例(原型设计模式)或单个共享实例(单例设计模式的高级替代方案,其中实例是工厂范围内的单例)。返回哪种类型的实例取决于bean工厂配置:API是相同的。自Spring2.0以来,根据具体的应用程序上下文(例如web环境中的“request”和“session”作用域),可以使用更多的作用域。


这种方式的要点是BeanFactory是应用程序组件的中心注册中心,它集成了应用程序组件的配置(例如,单个对象不再需要读取属性文件)。参阅“Expert One-on-One J2EE Design and Development”的第4章和第11章,以了解此方式的好处。


注意,通常最好依赖依赖注入(“push”配置)通过setter或构造函数配置应用程序对象,而不是像BeanFactory查找那样使用任何形式的“pull”配置。Spring的依赖注入功能是使用这个BeanFactory接口及其子接口实现的。


通常,BeanFactory将加载存储在配置源(如XML文档)中的bean定义,并使用org.springframework.beans包来配置bean。然而,实现可以直接在Java代码中返回它创建的Java对象。对于如何存储定义没有任何限制:LDAP、RDBMS、XML、属性文件等。鼓励实现支持bean之间的引用(依赖注入)。


与ListableBeanFactory中的方法相反,如果是HierarchicalBeanFactory,则接口中的所有操作也将检查父工厂。如果在此工厂实例中找不到bean,则会查询直接父工厂。工厂实例中的bean应该重写任何父工厂中同名的bean。 Bean工厂实现应该尽可能支持标准的Bean生命周期接口。


BeanFactory认识小结

Spring官方及源码中对BeanFactory进行了详细的解释,但是其中涉及了较多的概念,对于初学者来说,相对晦涩难懂,总结BeanFactory如下。


BeanFactory使用工厂方法的设计模式,作为一个工厂,它管理的对象被称为bean,bean可以是单例的,也可以是原型的,具体取决于bean定义。

BeanFactory并不关心bean的配置源来自何处,是何种格式,通过扩展最终都会被解析为BeanDefinition表示。

BeanFactory体系使用了分层设计的方式,BeanFactory是一个最基本的容器,Spring依赖注入功能是使用BeanFactory接口及其子接口实现的。

BeanFactory源码分析

BeanFactory作为基础的容器提供了很多获取bean信息的接口。


版本说明

源码使用的spring framework版本为5.2.6.RELEASE


BeanFactory类结构

image.png

BeanFactory字段

String FACTORY_BEAN_PREFIX = "&";

BeanFactory中仅包含一个名为FACTORY_BEAN_PREFIX的字段,获取bean时,如果bean名称以FACTORY_BEAN_PREFIX开头,并且bean的类型是FactoryBean,则表示要获取的bean是FactoryBean本身,而不是根据FactoryBean bean的实例获取的bean。


BeanFactory方法

获取bean实例的方法

Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

getBean方法用于实时查找bean,getBeanProvider方法用于延迟查找bean。

涉及的字段含义如下:


name:表示要获取的bean的名称或别名,一个bean必须有一个唯一的名称标识,但可以有多个别名。

requiredType:表示要获取的bean的类型,获取的bean的实际类型可以是该类型或该类型的子类。

args:构造方法或工厂方法的参数。spring中的bean可以通过构造方法直接创建,也可以使用配置的工厂方法进行创建。

返回值:


Object:如果没有指定所需的bean的类型,则会返回Object类型。

T:如果指定了所需的bean的类型,则spring会把bean转换为所需的类型。

ObjectProvider<T>:可以理解为bean对象的提供者,可以根据这个类中的方法延迟获取bean。

异常:


BeansException:如果不能创建bean或者无法获取到bean则抛出该异常。

获取bean特性的方法

// BeanFactory是否包含给定名称或别名的bean
boolean containsBean(String name);
// 给定名称或别名的bean在BeanFactory中是否为单例或原型的,如果没有给定名称的bean则抛出异常
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
// 给定名称的bean是否匹配给定的类型,如果没有给定名称的bean则抛出异常
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;


这些方法主要用于获取BeanFactory中bean是否具有某一种特性。

获取类型和别名的方法

  //获取给定名称的bean的类型,如果没有给定名称的bean则抛出异常,@Nullable说明返回值可能为null
  @Nullable
  Class<?> getType(String name) throws NoSuchBeanDefinitionException;
  //获取给定名称的bean的类型,allowFactoryBeanInit表示是否允许初始化FactoryBean以获取类型,如果没有给定名称的bean则抛出异常,@Nullable说明返回值可能为null
  @Nullable
  Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
  //获取给定名称的bean的别名
  String[] getAliases(String name);

知识扩展

org.springframework.lang.Nullable:spring 5.0新增的注解,可以注解到成员变量,方法参数,方法上,表示被注解的元素的值可能为null。

ObjectProvider:ObjectFactory的子类,在ObjectFactory的基础上添加了根据条件获取bean对象以及获取多个bean对象的方法,可用于延迟查找bean。

ResolvableType:简化泛型处理的工具类,可以轻易的获取到泛型类中的泛型类型。

总结

BeanFactory作为最基础的容器提供了获取bean信息的方法,并未涉及到bean信息的来源、如何解析bean元信息、如何实例化、初始化、销毁等,这些将在后面的文章进行分析。


目录
相关文章
|
2月前
|
XML Java 数据格式
编织Spring魔法:解读核心容器中的Beans机制【beans 一】
编织Spring魔法:解读核心容器中的Beans机制【beans 一】
42 0
|
1月前
|
Java 测试技术 数据库连接
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
|
1天前
|
XML Java 数据格式
手写spring第八章-定义标记类型Aware接口,实现感知容器对象
手写spring第八章-定义标记类型Aware接口,实现感知容器对象
4 0
|
2天前
|
设计模式 存储 Java
手写spring第二章-运用设计模式编写可扩展的容器
手写spring第二章-运用设计模式编写可扩展的容器
7 0
|
4天前
|
XML Java 数据格式
【spring】01 Spring容器研究
【spring】01 Spring容器研究
7 0
|
16天前
|
XML Java 数据格式
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
21 0
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
|
1月前
|
Java 容器 Spring
【spring(一)】核心容器总结
【spring(一)】核心容器总结
|
1月前
|
Java 开发者 容器
【Java】深入了解Spring容器的两个关键组件
【Java】深入了解Spring容器的两个关键组件
10 0
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (下)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)