关于java:Spring浅析一-BeanFactory-有啥可说的

33次阅读

共计 5838 个字符,预计需要花费 15 分钟才能阅读完成。

浏览 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 非亲非故。但实际上,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 工厂的相干学习与总结,如果错漏,欢送斧正。

正文完
 0