前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简单把 Spring 容器分为了两大类!

简单把 Spring 容器分为了两大类!

作者头像
江南一点雨
发布2023-09-20 09:04:16
2130
发布2023-09-20 09:04:16
举报
文章被收录于专栏:玩转JavaEE玩转JavaEE

这个问题松哥想了很久要怎么和大家展开介绍,最早我是想整一篇文章把 Spring 容器整个从头到尾捋一遍,但是,东西太多显然不现实,我还是倾向于通过不同的文章,从不同的角度来介绍 Spring 容器的一些使用细节,最后再将整体串通起来~

因此,今天我想先和大家聊一个小的话题,就是我们先来捋一捋 Spring 中真正干活的容器到底是哪个?

说到 Spring 容器,我们很容易想到 BeanFactory,大家很容易拿到这张图:

这张图大致上一看,有七八个能干活的容器,难道 Spring 中真的有这么多种不同的容器吗?那我们不妨想一想,容器的核心职责是什么?我们是否真的需要这么多容器?

其实,Spring 中,跟 Bean 最核心的功能相关的容器,只有三个!接下来我们来分析一下。

1. BeanFactory

BeanFactory 是所有容器的根,它里边提供了规范了最基本的容器方法和判断方法,例如如下一些方法:

  1. getBean(String name):根据给定的 Bean 名称获取对应的实例对象。此方法允许通过名称检索 Bean,如果找到匹配的 Bean,则返回该 Bean 的实例。
  2. getBean(String name, ClassrequiredType):根据给定的 Bean 名称和类型获取对应的实例对象。此方法允许通过名称和类型检索 Bean,如果找到匹配的 Bean,则返回该 Bean 的实例。
  3. getBean(ClassrequiredType):根据给定的类型获取对应的实例对象。此方法允许通过类型检索 Bean,如果找到匹配的 Bean,则返回该 Bean 的实例。
  4. getBean(Class, Object...):根据给定类型返回对应的实例对象,第二个参数是在构造给定的实例时构造方法所使用的参数。
  5. getBean(String, Object...):这个跟上一个方法类似,区别在于第一个参数传入的是 Bean 名称。
  6. getBeanProvider(Class):这个的作用是获取一个用于访问和管理 Bean 的提供者(BeanProvider)。BeanProvider 是一个泛型接口,它提供了一种延迟加载和按需获取 Bean 的机制。通过 getBeanProvider 方法,可以获取一个 BeanProvider 对象,然后可以使用该对象来获取特定类型的 Bean 实例。BeanProvider 具有延迟加载、按需获取以及安全访问等功能,这是 Spring5.1 刚刚推出的方法,所以大家目前来说应该见到的并不多。
  7. getBeanProvider(ResolvableType):这个等同于上面的方法,只不过传入的参数类型有差别。
  8. getType(String name):获取指定名称的 Bean 的类型。如果找到匹配的 Bean,则返回 Bean 的类型;如果找不到匹配的 Bean,则返回 null。
  9. getType(String, boolean):这个作用也是等价于上面这个方法,不同的是,多了一个 boolean 类型的参数,表示在获取类型的时候,是否提前将 FactoryBean 初始化,在之前的文章FactoryBean 和它的兄弟SmartFactoryBean!中松哥和大家聊了 FactoryBean 具备天然的延迟加载特性,这个方法也是 Spring5.2 开始才有的。
  10. containsBean(String name):检查容器中是否包含指定名称的 Bean。如果容器中存在具有给定名称的 Bean,则返回 true,否则返回 false。
  11. isSingleton(String name):检查指定名称的 Bean 是否为单例。如果指定名称的 Bean 是单例,则返回 true,否则返回 false。
  12. isPrototype(String name):检查指定名称的 Bean 是否为原型。如果指定名称的 Bean 是原型,则返回 true,否则返回 false。
  13. getAliases(String name):获取给定名称的 Bean 的所有别名。如果存在别名,则返回别名的数组;如果不存在别名,则返回空数组。
  14. isTypeMatch(String,ResolvableType):这个方法是判断给定的 Bean 名称是否和给定的类型相匹配。
  15. isTypeMatch(String,Class<?>):作用等价于上面这个方法。

BeanFactory 中常见的方法主要就是这些。这也是容器操作中最最核心的方法。

在本文一开始的类继承图中,BeanFactory 有很多实现类,那么是哪些实现类实现了上面这些方法呢?其实只有三个,分别是:

  • DefaultListableBeanFactory
  • StaticListableBeanFactory
  • SimpleJndiBeanFactory

别看实现类很多,但是其实干活的就是这三个。

1.1 DefaultListableBeanFactory

DefaultListableBeanFactory 是 Spring 框架中最常用的 bean 工厂之一。它是 BeanFactory 接口的一个实现类,同时也是 ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory 接口的实现类。DefaultListableBeanFactory 提供了丰富的功能来管理和访问 bean。

DefaultListableBeanFactory 的主要特点和功能包括:

  1. Bean 定义的注册和获取:DefaultListableBeanFactory 可以通过注册 BeanDefinition 对象来定义和配置 Bean。它提供了方法来注册、获取和移除 Bean 的定义。这使得我们可以在运行时动态地添加、修改和删除 Bean。
  2. Bean 的实例化和获取:DefaultListableBeanFactory 负责实例化和管理 Bean 的生命周期。它可以根据 Bean 的定义创建 Bean 的实例,并提供方法来获取 Bean 的实例。它支持单例、原型和其他作用域的 Bean。
  3. 依赖注入:DefaultListableBeanFactory 支持自动装配和显式依赖注入。它可以解析 Bean 之间的依赖关系,并在需要时自动注入依赖。它支持构造函数注入、属性注入和方法注入。
  4. AOP 支持:DefaultListableBeanFactory 支持面向切面编程 (AOP)。它可以通过配置切面和通知,实现横切关注点的模块化。
  5. Bean 生命周期管理:DefaultListableBeanFactory 提供了对 Bean 生命周期的管理。它可以在 Bean 初始化之前和销毁之后执行相应的回调方法。
  6. Bean 列表和查询:DefaultListableBeanFactory 实现了 ListableBeanFactory 接口,提供了一系列方法来获取 Bean 的列表信息。它支持按名称、类型和条件进行 Bean 的查询和获取。

总的来说,DefaultListableBeanFactory 是 Spring 框架中最常用的 Bean 工厂,它提供了丰富的功能来定义、配置、管理和访问 Bean,它的功能最完整也最成熟。它是实现依赖注入和控制反转 (IoC) 的核心组件之一。

我们平时开发用的各种“容器”其实都是 DefaultListableBeanFactory。

例如在松哥之前和大家讲的基本用法中,我们常用的两个类分别是 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext,这两个底层使用的容器其实就是 DefaultListableBeanFactory。

1.2 StaticListableBeanFactory

StaticListableBeanFactory 这个容器我们其实很少用到,但是这里大家也了解一下。

这个容器从名字上就能看出其特点:静态。不错,这是一个静态容器,它里边定义了一个 Map 集合,当你想要存储一个 Bean 的时候,它就给你存到这个 Map 集合中,当你想要获取一个 Bean 的时候,它就给你从这个 Map 集合中读取出来。

StaticListableBeanFactory 的主要特点和功能包括:

  1. 静态:StaticListableBeanFactory 在初始化时加载所有的 Bean 定义,并在运行时保持不变。这意味着它不支持在运行时动态修改或删除 Bean,适用于那些不需要动态修改 Bean 的场景,动态添加新的 Bean 是可以的。
  2. 列表化:StaticListableBeanFactory 实现了 ListableBeanFactory 接口,提供了一系列方法来获取 Bean 的列表信息。它可以通过名称、类型、注解等方式来获取 Bean,还支持按条件过滤和排序。
  3. 高效访问:由于所有的 Bean 定义在初始化时就加载完成,StaticListableBeanFactory 提供了高效访问 Bean 的能力。它不需要在运行时进行 Bean 的查找和创建,从而提供了更快的性能。
  4. 配置方式:StaticListableBeanFactory 可以通过配置文件或编程方式进行配置。它支持使用 XML、注解或 Java 配置类来定义和配置 Bean。

总的来说,StaticListableBeanFactory 提供了一种静态且列表化的方式来管理和访问 Bean。它适用于那些在运行时不需要动态修改 Bean 的应用场景,并且提供了方便的方法来获取和操作 Bean 的列表信息。

1.3 SimpleJndiBeanFactory

SimpleJndiBeanFactory 是 Spring 框架中的一个类,它是 BeanFactory 接口的一个实现类。SimpleJndiBeanFactory 使用简单的 JNDI (Java Naming and Directory Interface) 技术来管理和访问 Bean。

JNDI 是 Java 平台提供的一种标准 API,用于访问命名和目录服务。

SimpleJndiBeanFactory 利用 JNDI 的功能,可以从 JNDI 中查找和获取 Bean,以及执行与 JNDI 相关的操作。

SimpleJndiBeanFactory 的主要特点和功能包括:

  1. JNDI 支持:SimpleJndiBeanFactory 支持使用 JNDI 技术来管理和访问 Bean。它可以从 JNDI 中查找和获取 Bean,以及执行与 JNDI 相关的操作,如绑定、解绑等。
  2. 简单易用:SimpleJndiBeanFactory 提供了一种简单易用的方式来访问 JNDI 中的 Bean。它封装了 JNDI API 的复杂性,提供了更简洁的接口和方法。
  3. 配置方式:SimpleJndiBeanFactory 可以通过配置文件或编程方式进行配置。它支持使用简单的 properties 文件来配置 JNDI 上下文和 Bean 的绑定关系。
  4. 跨平台性:由于 JNDI 是 Java 平台的标准 API,SimpleJndiBeanFactory 具有良好的跨平台性,可以在不同的 Java 环境中使用。

老实说,这个 SimpleJndiBeanFactory 最大的特点就是利用了 JNDI 技术,然而,我们平时开发实际上很少会用到 JNDI 技术,所以这个容器其实用的并不多。

Spring 中的基础容器就这三个,其中被大量使用的是第一个 DefaultListableBeanFactory。

2. ApplicationContext

如果前面所说的三个容器(BeanFactory)是一个发动机,那么 ApplicationContext 就是一辆汽车,回顾本文一开始的类结构图,其实除了前面三个 BeanFactory 之外,其他的都算是 ApplicationContext 了。

BeanFactory 提供了 Bean 的核心功能,但是依然缺乏很多东西,例如配置文件要怎么加载?带注解的类谁去扫描?国际化怎么实现?事件的处理等等。。。这些功能上面三个核心类都没有!那么谁有呢?那就是 ApplicationContext 有。另外,Spring 中许多通过 BeanPostProcessor 实现的功能,通过 BeanFactory 也无法实现,因为直接使用 BeanFactory 并不会触发 BeanPostProcessor,如果非要使用,得自己手动去触发这些后置处理器的执行。

ApplicationContext 并非一个全新的容器,本质上,它里边使用的是 DefaultListableBeanFactory 容器,只不过在该容器的基础上继续增强了许多功能。

在 ApplicationContext 中,容器的初始化都是从 refresh 方法开始,该方法会调用 obtainFreshBeanFactory 方法去获取一个 ConfigurableListableBeanFactory 类型的容器,问题是 ConfigurableListableBeanFactory 只有一个实现类,那就是 DefaultListableBeanFactory,所以我们说,在 ApplicationContext 中使用的都是 DefaultListableBeanFactory 容器。

因此,在具体实践中,如果能够使用 ApplicationContext,就尽量不要直接使用 DefaultListableBeanFactory 或者其他容器,除非你想完全控制容器的运行。

下面这张表格列出来了 BeanFactory 和 ApplicationContext 之间的一些差别。

特性

BeanFactory

ApplicationContext

Bean 的实例化/注入

支持

支持

Bean 生命周期管理

不支持

支持

自动触发 BeanPostProcessor

不支持

支持

自动触发 BeanFactoryPostProcessor

不支持

支持

国际化(I18N)

不支持

支持

内置 ApplicationEvent 发布机制

不支持

支持

好啦,这样梳理一下,容器应该就好理解很多了,接下来的文章松哥会通过具体的案例,来和小伙伴们演示不同 BeanFactory 以及 ApplicationContext 的用法。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-09-19 10:36,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 江南一点雨 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. BeanFactory
    • 1.1 DefaultListableBeanFactory
      • 1.2 StaticListableBeanFactory
        • 1.3 SimpleJndiBeanFactory
        • 2. ApplicationContext
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档