BeanFactory和FactoryBean,ApplicationContext的关系

news/2025/2/12 15:10:52/
  • 他们的区别比较容易理解,从字面意思就能区分开来,BeanFactory是Bean工厂,而FactoryBean是工厂Bean
  • BeanFactory,Spring中工厂的顶层规范,他是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖
  • 它定义了getBean()、containsBean()等管理Bean的通用方法
  • 这是基本的 Spring 模块,提供 Spring 框架的基础功能,BeanFactory 是 任何以Spring 为基础的应用的核心
  • Spring 框架建立在此模块之上,它使 Spring 成为一个容器
  • Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从真正的应用代码中分离
  • 最常用的 BeanFactory 实现是 XmlBeanFactory 类
  • 它根据 XML 文件中的定义加载 beans;该容器从 XML 文件读取配置元数据并用它去创建一个完全配置的系统或应用
  • BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器
  • 其中ApplicationContext是BeanFactory的子接口
  • 依赖关系
  • BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系
  • ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:
    • 继承MessageSource,因此支持国际化
    • 统一的资源文件访问方式
    • 提供在监听器中注册bean的事件
    • 同时加载多个配置文件
    • 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层
  • 加载方式
  • BeanFactory采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化
  • 这样,我们就不能发现一些存在的Spring的配置问题
  • 如果Bean的某一个属性没有注入,BeanFactory加载后,直至第一次使用调用getBean方法才会抛出异常
  • ApplicationContext,它是在容器启动时,一次性创建了所有的Bean
  • 这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入
  • ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean,确保当你需要的时候,你就不用等待,因为它们已经创建好了
  • 相对于基本的BeanFactory,ApplicationContext唯一的不足是占用内存空间
  • 当应用程序配置Bean较多时,程序启动较慢
  • 创建方式
  • BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader
  • 注册方式
  • BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册
  • Spring设计了两个接口用以表示容器
    • BeanFactory
    • ApplicationContext
  • BeanFactory 粗暴简单,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例
  • 通常只提供注册(put),获取(get)这两个功能,可以称之为“低级容器”
  • ApplicationContext 可以称之为“高级容器”
  • 因为他比 BeanFactory 多了更多的功能
  • 他继承了多个接口,因此具备了更多的功能
  • 例如资源的获取,支持多种消息(例如 JSP tag 的支持),对 BeanFactory 多了工具级别的支持等待
  • 所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而是“应用上下文”,代表着整个大容器的所有功能
  • 该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的bean
  • 当然,除了这两个大接口,还有其他的辅助接口,但我今天不会花太多篇幅介绍他们
  • 为了更直观的展示 “低级容器” 和 “高级容器” 的关系,我这里通过常用的 ClassPathXmlApplicationContext类,来展示整个容器的层级 UML 关系

  • 最上面的 BeanFactory,下面的 3 个绿色的,都是功能扩展接口,这里就不展开讲
  • 看下面的隶属 ApplicationContext 粉红色的 “高级容器”,依赖着 “低级容器”,这里说的是依赖,不是继承
  • 他依赖着 “低级容器” 的 getBean 功能
  • 而高级容器有更多的功能:支持不同的信息源头,可以访问文件资源,支持应用事件(Observer 模式)
  • 通常用户看到的就是“高级容器”
  • 但 BeanFactory 也非常够用;左边灰色区域的是 “低级容器”,只负载加载 Bean,获取 Bean
  • 容器其他的高级功能是没有的
  • 例如上图画的 refresh 刷新 Bean 工厂所有配置,生命周期事件回调等
  • ApplicationContext通常的实现
    • FileSystemXmlApplicationContext:此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数
    • ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置
    • WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean
  • BeanFactory-框架基础设施
  • BeanFactory是Spring框架的基础设施,面向 Spring 本身;
  • ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的 BeanFactory

  • 1-BeanDefinitionRegistry 注册表
    • Spring 配置文件中每一个节点元素在 Spring 容器里都通过一个 BeanDefinition 对象表示,它描述了 Bean 的配置信息
    • 而 BeanDefinitionRegistry 接口提供了向容器手工注册 BeanDefinition 对象的方法
  • 2-BeanFactory 顶层接口
    • 位于类结构树的顶端,它最主要的方法就是 getBean(String beanName),该方法从容器中返回特定名称的 Bean
    • BeanFactory 的功能通过其他的接口得到不断扩展
  • 3-ListableBeanFactory
    • 该接口定义了访问容器中 Bean 基本信息的若干方法
    • 如查看 Bean 的个数、获取某一类型Bean 的配置名、查看容器中是否包括某一 Bean 等方法
  • 4-HierarchicalBeanFactory 父子级联
    • 父子级联 IoC 容器的接口,子容器可以通过接口方法访问父容器
    • 通过 HierarchicalBeanFactory 接口,Spring 的 IoC 容器可以建立父子层级关联的容器体系
    • 子容器可以访问父容器中的 Bean,但父容器不能访问子容器的 Bean
    • Spring 使用父子容器实现了很多功能,比如在 Spring MVC 中,展现层 Bean 位于一个子容器中,而业务层和持久层的 Bean 位于父容器中
    • 这样,展现层 Bean 就可以引用业务层和持久层的 Bean,而业务层和持久层的 Bean 则看不到展现层的 Bean
  • 5-ConfigurableBeanFactory
    • 是一个重要的接口,增强了 IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法
  • 6-AutowireCapableBeanFactory 自动装配
    • 定义了将容器中的 Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法
  • 7-SingletonBeanRegistry 运行期间注册单例 Bean
    • 定义了允许在运行期间向容器注册单实例 Bean 的方法
    • 对于单实例( singleton)的 Bean 来说,BeanFactory 会缓存 Bean 实例,所以第二次使用 getBean() 获取 Bean 时将直接从 IoC 容器的缓存中获取 Bean 实例
    • Spring 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例 Bean 的缓存器,它是一个用 HashMap 实现的缓存器,单实例的 Bean 以beanName 为键保存在这个 HashMap 中
  • 8-依赖日志框
    • 在初始化 BeanFactory 时,必须为其提供一种日志框架,比如使用 Log4J,即在类路径下提供 Log4J 配置文件,这样启动 Spring 容器才不会报错
  • ApplicationContext 面向开发应用
  • ApplicationContext 由 BeanFactory 派生而来,提供了更多面向实际应用的功能
  • ApplicationContext 继承了 HierarchicalBeanFactory 和 ListableBeanFactory 接口,在此基础上,还通过多个其他的接口扩展了 BeanFactory 的功能:

  • 1-ClassPathXmlApplicationContext:默认从类路径加载配置文件
  • 2-FileSystemXmlApplicationContext:默认从文件系统中装载配置文件
  • 3-ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事件、关闭事件等
  • 4-MessageSource:为应用提供 i18n 国际化消息访问的功能
  • 5-ResourcePatternResolver:所有 ApplicationContext 实现类都实现了类似于 PathMatchingResourcePatternResolver 的功能,可以通过带前缀的 Ant 风格的资源文件路径装载 Spring 的配置文件
  • 6-LifeCycle:该接口是 Spring 2.0 加入的,该接口提供了 start() 和 stop() 两个方法,主要用于控制异步处理过程;在具体使用时,该接口同时被 ApplicationContext 实现及具体 Bean 实现,ApplicationContext 会将 start/stop 的信息传递给容器中所有实现了该接口的 Bean,以达到管理和控制 JMX、任务调度等目的
  • 7-ConfigurableApplicationContext 扩展于 ApplicationContext,它新增加了两个主要的方法:refresh() 和 close(),让 ApplicationContext 具有启动、刷新和关闭应用上下文的能力;在应用上下文关闭的情况下调用 refresh() 即可启动应用上下文,在已经启动的状态下,调用 refresh() 则清除缓存并重新装载配置信息,而调用 close() 则可关闭应用上下文
  • Spring容器中有两种Bean:普通Bean和工厂Bean
  • Spring直接使用前者,FactoryBean跟普通Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象

  • Spring通过反射机制利用的class属性指定的实现类来实例化bean
  • 在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在其中提供大量的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可能会得到更好的效果
  • Spring为此提供了一个org.Springframework.beans.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑
  • Spring框架本身就自带了实现FactoryBean的70多个接口,如ProxyFactoryBean、MapFactoryBean、PropertiesFactoryBean等

http://www.ppmy.cn/news/1140084.html

相关文章

【Element UI】解决 el-dialog 弹框组件设置 custom-class 样式不生效问题

文章目录 问题描述解决方法 问题描述 <template><el-dialog class"myDialog" v-model"show" title"弹窗" custom-class"customDialog"><div>弹窗内容</div></el-dialog> </template> <script…

java api System类

currentTimeMills() package daysreplace;public class Test {public static void main(String[] args) {long start System.currentTimeMillis();// System.out.println(start"毫秒");for (int i 0; i < 100; i) {System.out.println("计算执行100次输出…

SQLite3数据类型

存储类与数据类型 NULLINTEGER 有符号整数类型&#xff0c;存储为0,1,2,3,4,6或8个字节&#xff0c;取决于值的大小。REAL 浮点类型&#xff0c;存储为8字节的IEEE浮点数。TEXT 文本类型&#xff0c;将使用数据库指定的编码格式存储&#xff08;UTF-8,UTF-16BE,UTF-16LE)BLOB …

【Overload游戏引擎分析】编辑器对象鼠标拾取原理

Overload的场景视图区有拾取鼠标功能&#xff0c;单击拾取物体后会显示在Inspector面板中。本文来分析鼠标拾取这个功能背后的原理。 一、OpenGL的FrameBuffer 实现鼠标拾取常用的方式有两种&#xff1a;渲染id到纹理、光线投射求交。Overload使用的是渲染id到纹理&#xff0c…

成功解决@Async注解不生效的问题,异步任务处理问题

首先&#xff0c;有这样一个异步监听方法 然后配置好了异步线程池 package com.fdw.study.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Conf…

数百个下载能够传播 Rootkit 的恶意 NPM 软件包

供应链安全公司 ReversingLabs 警告称&#xff0c;最近观察到的一次恶意活动依靠拼写错误来诱骗用户下载恶意 NPM 软件包&#xff0c;该软件包会通过 rootkit 感染他们的系统。 该恶意软件包名为“node-hide-console-windows”&#xff0c;旨在模仿 NPM 存储库上合法的“node-…

网络代理技术:保障隐私与增强安全

在当今高度互联的数字世界中&#xff0c;网络代理技术正逐渐崭露头角&#xff0c;为用户提供了保护隐私和增强网络安全的有力工具。本文将深入探讨Socks5代理、IP代理以及它们在网络安全、爬虫开发中的应用&#xff0c;助您更好地理解和利用这些技术。 1. Socks5代理&#xff…

Python-Scrapy框架(框架学习)

一、概述 Scrapy是一个用于爬取网站数据的Python框架&#xff0c;可以用来抓取web站点并从页面中提取结构化的数据。 基本组件&#xff1a; 引擎(Engine)&#xff1a;负责控制整个爬虫的流程&#xff0c;包括调度请求、处理请求和响应等。 调度器(Scheduler)&#xff1a;负责…